diff options
Diffstat (limited to 'app')
376 files changed, 3309 insertions, 6001 deletions
diff --git a/app/assets/images/favicon-blue.ico b/app/assets/images/favicon-blue.ico Binary files differindex 156fcf07588..156fcf07588 100755..100644 --- a/app/assets/images/favicon-blue.ico +++ b/app/assets/images/favicon-blue.ico diff --git a/app/assets/images/icons.json b/app/assets/images/icons.json index e5da75faf38..6b8f85e37fd 100644 --- a/app/assets/images/icons.json +++ b/app/assets/images/icons.json @@ -1 +1 @@ -{"iconCount":134,"icons":["abuse","account","admin","angle-double-left","angle-down","angle-left","angle-right","angle-up","appearance","applications","approval","arrow-right","assignee","bold","book","branch","calendar","cancel","chevron-down","chevron-left","chevron-right","chevron-up","clock","code","comment-dots","comment-next","comment","comments","commit","credit-card","disk","doc_code","doc_image","doc_text","download","duplicate","earth","eye-slash","eye","file-additions","file-deletion","file-modified","filter","folder","fork","geo-nodes","git-merge","group","history","home","hook","issue-block","issue-child","issue-close","issue-duplicate","issue-new","issue-open-m","issue-open","issue-parent","issues","key-2","key","label","labels","leave","level-up","license","link","list-bulleted","list-numbered","location-dot","location","lock-open","lock","log","mail","merge-request-close-m","merge-request-close","messages","mobile-issue-close","monitor","more","notifications-off","notifications","overview","pencil","pipeline","play","plus-square-o","plus-square","plus","preferences","profile","project","push-rules","question-o","question","quote","redo","remove","repeat","retry","scale","screen-full","screen-normal","search","settings","shield","slight-frown","slight-smile","smile","smiley","snippet","spam","star-o","star","stop","talic","task-done","template","thump-down","thump-up","timer","todo-add","todo-done","token","unapproval","unassignee","unlink","user","users","volume-up","warning","work"]}
\ No newline at end of file +{"iconCount":135,"spriteSize":58718,"icons":["abuse","account","admin","angle-double-left","angle-double-right","angle-down","angle-left","angle-right","angle-up","appearance","applications","approval","arrow-right","assignee","bold","book","branch","calendar","cancel","chevron-down","chevron-left","chevron-right","chevron-up","clock","close","code","comment-dots","comment-next","comment","comments","commit","credit-card","disk","doc_code","doc_image","doc_text","download","duplicate","earth","eye-slash","eye","file-additions","file-deletion","file-modified","filter","folder","fork","geo-nodes","git-merge","group","history","home","hook","issue-block","issue-child","issue-close","issue-duplicate","issue-new","issue-open-m","issue-open","issue-parent","issues","key-2","key","label","labels","leave","level-up","license","link","list-bulleted","list-numbered","location-dot","location","lock-open","lock","log","mail","merge-request-close","messages","mobile-issue-close","monitor","more","notifications-off","notifications","overview","pencil","pipeline","play","plus-square-o","plus-square","plus","preferences","profile","project","push-rules","question-o","question","quote","redo","remove","repeat","retry","scale","screen-full","screen-normal","search","settings","shield","slight-frown","slight-smile","smile","smiley","snippet","spam","star-o","star","stop","talic","task-done","template","thump-down","thump-up","timer","todo-add","todo-done","token","unapproval","unassignee","unlink","user","users","volume-up","warning","work"]}
\ No newline at end of file diff --git a/app/assets/images/icons.svg b/app/assets/images/icons.svg index 5c3a9962bd3..30cb2109ec2 100644 --- a/app/assets/images/icons.svg +++ b/app/assets/images/icons.svg @@ -1 +1 @@ -<?xml version="1.0" encoding="utf-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><symbol viewBox="0 0 16 16" id="abuse" xmlns="http://www.w3.org/2000/svg"><path d="M11.408.328l4.029 3.222A1.5 1.5 0 0 1 16 4.72v6.555a1.5 1.5 0 0 1-.563 1.171l-4.026 3.224a1.5 1.5 0 0 1-.937.329H5.529a1.5 1.5 0 0 1-.937-.328L.563 12.45A1.5 1.5 0 0 1 0 11.28V4.724a1.5 1.5 0 0 1 .563-1.171L4.589.329A1.5 1.5 0 0 1 5.526 0h4.945c.34 0 .67.116.937.328zM10.296 2H5.702L2 4.964v6.074L5.704 14h4.594L14 11.036V4.962L10.296 2zM8 4a1 1 0 0 1 1 1v3a1 1 0 1 1-2 0V5a1 1 0 0 1 1-1zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="account" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M9.195 9.965l-.568-.875a.25.25 0 0 1 .015-.294l.405-.5a.25.25 0 0 1 .283-.075l.938.36c.257-.183.543-.325.851-.42l.322-.988A.25.25 0 0 1 11.679 7h.642a.25.25 0 0 1 .238.173l.322.988c.308.095.594.237.851.42l.938-.36a.25.25 0 0 1 .283.076l.405.5a.25.25 0 0 1 .015.293l-.568.875c.113.297.18.616.193.95l.898.54a.25.25 0 0 1 .115.27l-.144.626a.25.25 0 0 1-.222.193l-1.115.098a3.015 3.015 0 0 1-.512.608l.165 1.18a.25.25 0 0 1-.138.259l-.577.281a.25.25 0 0 1-.29-.05l-.874-.905a3.035 3.035 0 0 1-.608 0l-.875.904a.25.25 0 0 1-.289.051l-.577-.281a.25.25 0 0 1-.138-.26l.165-1.18a3.015 3.015 0 0 1-.512-.607l-1.115-.098a.25.25 0 0 1-.222-.193l-.144-.626a.25.25 0 0 1 .115-.27l.898-.54c.013-.334.08-.653.193-.95zM6.789 8.023A12.845 12.845 0 0 0 6 8c-5.036 0-6 2.74-6 4.48C0 14.22.076 15 6 15c.553 0 1.055-.006 1.51-.02A5.977 5.977 0 0 1 6 11c0-1.083.287-2.1.79-2.977zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6zM12 12a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="admin" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M13.162 2.5a3.5 3.5 0 0 1-3.163 5.479L6.08 14.766a1.5 1.5 0 0 1-2.598-1.5L7.4 6.479A3.5 3.5 0 0 1 10.564 1L8.9 3.88l2.599 1.5 1.663-2.88zm-8.63 11.949a.5.5 0 1 0 .5-.866.5.5 0 0 0-.5.866z"/></symbol><symbol viewBox="0 0 16 16" id="angle-double-left" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10.414 7.95l4.243-4.243a1 1 0 0 0-1.414-1.414l-4.95 4.95a.997.997 0 0 0 0 1.414l4.95 4.95a1 1 0 1 0 1.414-1.415L10.414 7.95zm-7 0l4.243-4.243a1 1 0 0 0-1.414-1.414l-4.95 4.95a.997.997 0 0 0 0 1.414l4.95 4.95a1 1 0 0 0 1.414-1.415L3.414 7.95z"/></symbol><symbol viewBox="0 0 16 16" id="angle-down" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8 10.243l-4.95-4.95a1 1 0 0 0-1.414 1.414l5.657 5.657a.997.997 0 0 0 1.414 0l5.657-5.657a1 1 0 0 0-1.414-1.414L8 10.243z"/></symbol><symbol viewBox="0 0 16 16" id="angle-left" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M5.757 8l4.95-4.95a1 1 0 1 0-1.414-1.414L3.636 7.293a.997.997 0 0 0 0 1.414l5.657 5.657a1 1 0 0 0 1.414-1.414L5.757 8z"/></symbol><symbol viewBox="0 0 16 16" id="angle-right" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10.243 8l-4.95-4.95a1 1 0 0 1 1.414-1.414l5.657 5.657a.997.997 0 0 1 0 1.414l-5.657 5.657a1 1 0 0 1-1.414-1.414L10.243 8z"/></symbol><symbol viewBox="0 0 16 16" id="angle-up" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8 6.757l-4.95 4.95a1 1 0 1 1-1.414-1.414l5.657-5.657a.997.997 0 0 1 1.414 0l5.657 5.657a1 1 0 0 1-1.414 1.414L8 6.757z"/></symbol><symbol viewBox="0 0 16 16" id="appearance" xmlns="http://www.w3.org/2000/svg"><path d="M11.161 12.456l.232.121c.1.053.175.094.249.137.53.318.844.75.857 1.402.012 1.397-1.116 1.756-3.12 1.858a23.85 23.85 0 0 1-1.38.026A8 8 0 0 1 0 8a8 8 0 0 1 8-8c4.417 0 7.998 3.582 7.998 7.977.06 2.621-1.312 3.586-4.48 3.648-.602.008-1.068.043-1.4.104.228.192.598.47 1.043.727zm-3.287-.943c-.019-1.495 1.228-1.856 3.611-1.888C13.67 9.582 14.028 9.33 13.998 8A6 6 0 1 0 8 14c.603 0 .91-.004 1.277-.023a9.7 9.7 0 0 0 .478-.035c-1.172-.738-1.868-1.47-1.88-2.43zM6 5a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm6 3a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm-2-3a1 1 0 1 1 0-2 1 1 0 0 1 0 2zM4 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="applications" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M1 0h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1V1a1 1 0 0 1 1-1zm0 6h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1zm6-6h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V1a1 1 0 0 1 1-1zm0 1v2h2V1H7zm0 5h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1zm6-6h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1V1a1 1 0 0 1 1-1zm0 6h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1zm0 1v2h2V7h-2zM1 12h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1zm0 1v2h2v-2H1zm6-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1zm6 0h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1z"/></symbol><symbol viewBox="0 0 16 16" id="approval" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10.536 10.657l2.828-2.829a1 1 0 0 1 1.414 1.415l-3.535 3.535a.997.997 0 0 1-1.415 0l-2.12-2.121A1 1 0 1 1 9.12 9.243l1.415 1.414zM7.632 8.109A2 2 0 0 0 7 11.364l2.121 2.121a1.996 1.996 0 0 0 2.807.021C11.686 14.554 10.627 15 6 15c-5.924 0-6-.78-6-2.52S.964 8 6 8c.6 0 1.142.038 1.632.109zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6z"/></symbol><symbol viewBox="0 0 16 16" id="arrow-right" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M9 6H2a2 2 0 1 0 0 4h7v2.586a1 1 0 0 0 1.707.707l4.586-4.586a1 1 0 0 0 0-1.414l-4.586-4.586A1 1 0 0 0 9 3.414V6z"/></symbol><symbol viewBox="0 0 16 16" id="assignee" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M12 5V4a1 1 0 0 1 2 0v1h1a1 1 0 0 1 0 2h-1v1a1 1 0 0 1-2 0V7h-1a1 1 0 0 1 0-2h1zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6zM6 15c-5.924 0-6-.78-6-2.52S.964 8 6 8s6 2.692 6 4.48c0 1.788-.076 2.52-6 2.52z"/></symbol><symbol viewBox="0 0 16 16" id="bold" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M2 15V1a1 1 0 0 1 1-1h4.604c.93 0 1.762.088 2.495.264.733.176 1.353.445 1.863.807.509.363.897.82 1.164 1.369.268.549.401 1.197.401 1.945 0 .366-.045.718-.137 1.055-.091.337-.23.652-.417.945a3.453 3.453 0 0 1-.71.796 3.645 3.645 0 0 1-1.021.588c.469.117.87.295 1.203.533.333.238.608.515.824.83.216.315.374.657.473 1.027.099.37.148.75.148 1.138 0 1.553-.5 2.725-1.5 3.516-1 .791-2.423 1.187-4.27 1.187H3a1 1 0 0 1-1-1zm3.297-5.967v4.319H8.12c.425 0 .791-.053 1.099-.16.307-.106.564-.252.769-.44.205-.186.357-.406.456-.659.099-.252.148-.529.148-.83a3.04 3.04 0 0 0-.131-.928 1.78 1.78 0 0 0-.413-.703 1.8 1.8 0 0 0-.73-.445c-.3-.103-.66-.154-1.077-.154H5.297zm0-2.33h2.44c.842-.014 1.468-.192 1.878-.533.41-.34.616-.826.616-1.456 0-.725-.21-1.247-.632-1.566-.421-.318-1.086-.478-1.995-.478H5.297v4.033z"/></symbol><symbol viewBox="0 0 16 16" id="book" xmlns="http://www.w3.org/2000/svg"><path d="M7 2H5a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2v4.191a.5.5 0 0 1-.724.447l-1.052-.526a.5.5 0 0 0-.448 0l-1.052.526A.5.5 0 0 1 7 6.191V2zM5 0h6a4 4 0 0 1 4 4v8a4 4 0 0 1-4 4H5a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4z"/></symbol><symbol viewBox="0 0 16 16" id="branch" xmlns="http://www.w3.org/2000/svg"><path d="M6 11.978v.29a2 2 0 1 1-2 0V3.732a2 2 0 1 1 2 0v3.849c.592-.491 1.31-.854 2.15-1.081 1.308-.353 1.875-.882 1.893-1.743a2 2 0 1 1 2.002-.051C12.053 6.54 10.857 7.84 8.67 8.43 7.056 8.867 6.195 9.98 6 11.978zM5 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm6 1a1 1 0 1 0 0-2 1 1 0 0 0 0 2zM5 15a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="calendar" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M12 2h2a2 2 0 0 1 2 2H0a2 2 0 0 1 2-2h2V1a1 1 0 1 1 2 0v1h4V1a1 1 0 1 1 2 0v1zM0 4h16v9a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V4zm2 2.5V13a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V6.5a.5.5 0 0 0-.5-.5h-11a.5.5 0 0 0-.5.5zM5 8h2a1 1 0 1 1 0 2H5a1 1 0 1 1 0-2z"/></symbol><symbol viewBox="0 0 16 16" id="cancel" xmlns="http://www.w3.org/2000/svg"><path d="M3.11 4.523a6 6 0 0 0 8.367 8.367L3.109 4.524zM4.522 3.11l8.368 8.368A6 6 0 0 0 4.524 3.11zM8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16z"/></symbol><symbol viewBox="0 0 16 16" id="chevron-down" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8.078 8.2l3.535-3.536a2 2 0 0 1 2.828 2.828l-4.949 4.95c-.39.39-.902.586-1.414.586a1.994 1.994 0 0 1-1.414-.586l-4.95-4.95a2 2 0 1 1 2.828-2.828l3.536 3.535z"/></symbol><symbol viewBox="0 0 16 16" id="chevron-left" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7.977 7.998l3.535-3.535a2 2 0 1 0-2.828-2.828l-4.95 4.949c-.39.39-.586.902-.586 1.414 0 .512.196 1.024.586 1.414l4.95 4.95a2 2 0 1 0 2.828-2.828L7.977 7.998z"/></symbol><symbol viewBox="0 0 16 16" id="chevron-right" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8.22 7.998L4.683 4.463a2 2 0 0 1 2.828-2.828l4.95 4.949c.39.39.586.902.586 1.414a1.99 1.99 0 0 1-.586 1.414l-4.95 4.95a2 2 0 0 1-2.828-2.828l3.535-3.536z"/></symbol><symbol viewBox="0 0 16 16" id="chevron-up" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7.778 8.957l3.535 3.535a2 2 0 1 0 2.828-2.828l-4.949-4.95a1.994 1.994 0 0 0-1.414-.586c-.512 0-1.024.196-1.414.586l-4.95 4.95a2 2 0 1 0 2.828 2.828l3.536-3.535z"/></symbol><symbol viewBox="0 0 16 16" id="clock" xmlns="http://www.w3.org/2000/svg"><path d="M9 7h1a1 1 0 0 1 0 2H8a.997.997 0 0 1-1-1V5a1 1 0 1 1 2 0v2zm-1 9A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12z"/></symbol><symbol viewBox="0 0 16 16" id="code" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M15.871 8.243a.997.997 0 0 0-.293-.707L12.75 4.707a1 1 0 0 0-1.414 1.414l2.12 2.122-2.12 2.121a1 1 0 0 0 1.414 1.414l2.828-2.828a.997.997 0 0 0 .293-.707zm-13.243 0L4.75 6.12a1 1 0 1 0-1.414-1.414L.507 7.536a.997.997 0 0 0 0 1.414l2.829 2.828a1 1 0 1 0 1.414-1.414L2.628 8.243zm6.407-4.107a1 1 0 0 1 .707 1.225L8.19 11.157a1 1 0 1 1-1.931-.518L7.81 4.843a1 1 0 0 1 1.224-.707z"/></symbol><symbol viewBox="0 0 16 16" id="comment" xmlns="http://www.w3.org/2000/svg"><path d="M1.707 15.707C1.077 16.337 0 15.891 0 15V3a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H5.414l-3.707 3.707zM2 12.586l2.293-2.293A1 1 0 0 1 5 10h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v9.586z"/></symbol><symbol viewBox="0 0 16 16" id="comment-dots" xmlns="http://www.w3.org/2000/svg"><path d="M1.707 15.707C1.077 16.337 0 15.891 0 15V3a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H5.414l-3.707 3.707zM2 12.586l2.293-2.293A1 1 0 0 1 5 10h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v9.586zM5 7a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="comment-next" xmlns="http://www.w3.org/2000/svg"><path d="M8 5V4a.5.5 0 0 1 .8-.4l2.667 2a.5.5 0 0 1 0 .8L8.8 8.4A.5.5 0 0 1 8 8V7H6a1 1 0 1 1 0-2h2zM1.707 15.707C1.077 16.337 0 15.891 0 15V3a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H5.414l-3.707 3.707zM2 12.586l2.293-2.293A1 1 0 0 1 5 10h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v9.586z"/></symbol><symbol viewBox="0 0 16 16" id="comments" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M3.75 10L0 13V3a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2H3.75zM13 5h1a2 2 0 0 1 2 2v8l-2.667-2H8a2 2 0 0 1-2-2h4a3 3 0 0 0 3-3V5z"/></symbol><symbol viewBox="0 0 16 16" id="commit" xmlns="http://www.w3.org/2000/svg"><path d="M8 10a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm3.876-1.008a4.002 4.002 0 0 1-7.752 0A1.01 1.01 0 0 1 4 9H1a1 1 0 1 1 0-2h3c.042 0 .083.003.124.008a4.002 4.002 0 0 1 7.752 0A1.01 1.01 0 0 1 12 7h3a1 1 0 0 1 0 2h-3a1.01 1.01 0 0 1-.124-.008z"/></symbol><symbol viewBox="0 0 16 16" id="credit-card" xmlns="http://www.w3.org/2000/svg"><path d="M14 5a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1h12zm0 3H2v3a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V8zM3 2h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3zm6.5 8h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1z"/></symbol><symbol viewBox="0 0 16 16" id="disk" xmlns="http://www.w3.org/2000/svg"><path d="M16 11.764V3a3 3 0 0 0-3-3H3a3 3 0 0 0-3 3v8.764A2.989 2.989 0 0 1 2 11V3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v8c.768 0 1.47.289 2 .764zM2 12h12a2 2 0 1 1 0 4H2a2 2 0 1 1 0-4zm10 1a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"/></symbol><symbol viewBox="0 0 16 16" id="doc_code" xmlns="http://www.w3.org/2000/svg"><path d="M8 2H5a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V7h-3a2 2 0 0 1-2-2V2zm2 .414V5h2.586L10 2.414zm1.036 7.607a.498.498 0 0 1-.147.354l-1.414 1.414a.5.5 0 0 1-.707-.707l1.06-1.06-1.06-1.061a.5.5 0 0 1 .707-.707l1.414 1.414a.498.498 0 0 1 .147.353zm-4.822 0l1.06 1.061a.5.5 0 0 1-.706.707l-1.414-1.414a.498.498 0 0 1 0-.707l1.414-1.414a.5.5 0 1 1 .707.707l-1.06 1.06zM5 0h4.586A2 2 0 0 1 11 .586L14.414 4A2 2 0 0 1 15 5.414V12a4 4 0 0 1-4 4H5a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4z"/></symbol><symbol viewBox="0 0 16 16" id="doc_image" xmlns="http://www.w3.org/2000/svg"><path d="M8 2H5a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V7h-3a2 2 0 0 1-2-2V2zm2 .414V5h2.586L10 2.414zM7.333 9.667l1.313-1.313a.5.5 0 0 1 .708 0L12 11H4l2.188-1.75a.5.5 0 0 1 .624 0l.521.417zM5 0h4.586A2 2 0 0 1 11 .586L14.414 4A2 2 0 0 1 15 5.414V12a4 4 0 0 1-4 4H5a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4zm.5 8a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zM4 11h8v.7a.3.3 0 0 1-.3.3H4.3a.3.3 0 0 1-.3-.3V11z"/></symbol><symbol viewBox="0 0 16 16" id="doc_text" xmlns="http://www.w3.org/2000/svg"><path d="M8 2H5a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V7h-3a2 2 0 0 1-2-2V2zm2 .414V5h2.586L10 2.414zM5 0h4.586A2 2 0 0 1 11 .586L14.414 4A2 2 0 0 1 15 5.414V12a4 4 0 0 1-4 4H5a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4zm.5 11h5a.5.5 0 1 1 0 1h-5a.5.5 0 1 1 0-1zm0-2h5a.5.5 0 1 1 0 1h-5a.5.5 0 0 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1z"/></symbol><symbol viewBox="0 0 16 16" id="download" xmlns="http://www.w3.org/2000/svg"><path d="M9 12h1a.5.5 0 0 1 .4.8l-2 2.667a.5.5 0 0 1-.8 0l-2-2.667A.5.5 0 0 1 6 12h1V8a1 1 0 1 1 2 0v4zM4 9a1 1 0 1 1 0 2 4 4 0 0 1-1.971-7.481 4 4 0 0 1 6.633-2.505 3.999 3.999 0 0 1 3.82 2.014A4 4 0 0 1 12 11a1 1 0 0 1 0-2 2 2 0 1 0 0-4h-1a2 2 0 0 0-3.112-1.662A2 2 0 1 0 4.268 5H4a2 2 0 1 0 0 4z"/></symbol><symbol viewBox="0 0 16 16" id="duplicate" xmlns="http://www.w3.org/2000/svg"><path d="M14 10h-3a1 1 0 0 1-1-1V6H8.527A.527.527 0 0 0 8 6.527V13a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1v-3zm-4-7H8.527c-.18 0-.355.013-.527.04V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2v2H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h4a3 3 0 0 1 3 3zM8.527 4h2.323a.5.5 0 0 1 .35.143l4.65 4.551a.5.5 0 0 1 .15.357V13a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V6.527A2.527 2.527 0 0 1 8.527 4z"/></symbol><symbol viewBox="0 0 16 16" id="earth" xmlns="http://www.w3.org/2000/svg"><path d="M8.7 2.04l-.082.177c.283.223.422.413.417.571-.008.237-.311.057-.444.274-.133.218.038.542-.112.637-.15.096-.398-.386-.479-.46-.054-.049-.166-.257-.336-.625l-.216-.225a.844.844 0 0 0-.418-.035c-.177.038-.075.1-.035.132.04.032.32.037.452.2.132.164.03.224-.05.298-.054.05-.157.062-.31.035H5.952l-.402.398.03.325.229.455.324-.463c.008-.206.058-.342.15-.41.14-.1.342-.15.534-.085.191.066-.057.218.011.271.068.053.204-.098.313-.02.11.08.07.155.104.322.036.167.254.114.398.328.144.215.19.29.147.483-.043.195-.168.26-.305.232-.138-.028-.107-.246-.275-.348-.168-.102-.266-.114-.386-.054-.12.06-.016.129.023.235.04.106.274.321.224.43-.05.107-.108.116-.42 0-.21-.077-.414-.007-.615.212l-.76.722c-.153.715-.3 1.13-.44 1.243-.211.17-.177-.483-.483-.656-.306-.174-.494-.047-.8-.07-.307-.023-.42.65-.38.873a.434.434 0 0 0 .221.321c.236-.141.39-.184.465-.128.11.084-.144.267-.074.425.07.158.314.069.386.283.073.213.084.48-.05.706-.135.227-.275.178-.4.053-.127-.126-.033-.375-.255-.704-.223-.329-.381-.337-.63-.787-.158-.287-.35-.743-.575-1.366a6 6 0 0 0 3.21 7.198l.001-.075c0-.577-.004-.944-.012-1.102-.011-.236-.95-.945-1.104-1.2-.154-.256-.34-.595-.355-.746-.016-.151.185-.232.344-.325.16-.093-.11-.367.028-.626.137-.258.395-.438.496-.356.101.081.058.228.267.333.209.104.077-.213.456-.178.38.035.143.201.252.216.11.016.113-.127.299-.143.186-.015.282.445.471.622.19.178.452.008.611.043.159.034.267.09.402.255.136.166-.03.352.073.557.103.205 1.07.22 1.433.255.364.034.371.011.371.324s-.166.314-.453.507c-.286.193-.166.462-.38.762-.212.3-.316.062-.622.14-.306.077-.413.382-.452.568-.039.186-.386.094-.877.232-.29.082-.429.144-.569.204a6.002 6.002 0 0 0 7.682-4.3c-.094-.384-.18-.63-.258-.74-.213-.297-.36.21-.924.49-.564.278-.57-.288-.81-.49-.16-.133-.212-.44-.158-.92-.005-.478.02-.828.077-1.049.057-.221.126-.543.207-.965.351-.373.606-.572.764-.595.237-.034.336.374.658.3a.315.315 0 0 0 .035-.01 5.993 5.993 0 0 0-.475-.824l-.309-.043a.646.646 0 0 0-.332-.117c-.205-.02-.025.128-.089.24-.064.112-.235.724-.437.685-.201-.039-.204-.374-.17-.668.036-.294-.077-.35-.2-.412-.124-.062-.325-.213-.556-.295-.232-.082-.123-.175-.093-.274.03-.1.208-.015.193-.058-.014-.044-.313-.135-.266-.167.03-.02.2-.02.506.003l.216-.012.293-.163a.58.58 0 0 0-.376-.22c-.233-.036-.513-.034-.73-.142-.205-.103-.458-.36-.643-.638A5.965 5.965 0 0 0 8.7 2.04zM8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16z"/></symbol><symbol viewBox="0 0 16 16" id="eye" xmlns="http://www.w3.org/2000/svg"><path d="M8 14C4.816 14 2.253 12.284.393 8.981a2 2 0 0 1 0-1.962C2.253 3.716 4.816 2 8 2s5.747 1.716 7.607 5.019a2 2 0 0 1 0 1.962C13.747 12.284 11.184 14 8 14zm0-2c2.41 0 4.338-1.29 5.864-4C12.338 5.29 10.411 4 8 4 5.59 4 3.662 5.29 2.136 8 3.662 10.71 5.589 12 8 12zm0-1a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm1-3a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="eye-slash" xmlns="http://www.w3.org/2000/svg"><path d="M13.618 2.62L1.62 14.619a1 1 0 0 1-.985-1.668l1.525-1.526C1.516 10.742.926 9.927.393 8.981a2 2 0 0 1 0-1.962C2.253 3.716 4.816 2 8 2c1.074 0 2.076.195 3.006.58l.944-.944a1 1 0 0 1 1.668.985zM8.068 11a3 3 0 0 0 2.931-2.932l-2.931 2.931zm-3.02-2.462a3 3 0 0 1 3.49-3.49l.884-.884A6.044 6.044 0 0 0 8 4C5.59 4 3.662 5.29 2.136 8c.445.79.924 1.46 1.439 2.011l1.473-1.473zm.421 5.06l1.658-1.658c.283.04.575.06.873.06 2.41 0 4.338-1.29 5.864-4a11.023 11.023 0 0 0-1.133-1.664l1.418-1.418a12.799 12.799 0 0 1 1.458 2.1 2 2 0 0 1 0 1.963C13.747 12.284 11.184 14 8 14a7.883 7.883 0 0 1-2.53-.402z"/></symbol><symbol viewBox="0 0 16 16" id="file-additions" xmlns="http://www.w3.org/2000/svg"><path d="M7 7V5a1 1 0 1 1 2 0v2h2a1 1 0 0 1 0 2H9v2a1 1 0 0 1-2 0V9H5a1 1 0 1 1 0-2h2zM3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2H3z"/></symbol><symbol viewBox="0 0 16 16" id="file-deletion" xmlns="http://www.w3.org/2000/svg"><path d="M3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2H3zm2 6h6a1 1 0 0 1 0 2H5a1 1 0 1 1 0-2z"/></symbol><symbol viewBox="0 0 16 16" id="file-modified" xmlns="http://www.w3.org/2000/svg"><path d="M3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2H3zm5 4a3 3 0 1 1 0 6 3 3 0 0 1 0-6z"/></symbol><symbol viewBox="0 0 16 16" id="filter" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 6v9l-3.724-1.862A.5.5 0 0 1 6 12.691V6L1.854 1.854A.5.5 0 0 1 2.207 1h11.586a.5.5 0 0 1 .353.854L10 6z"/></symbol><symbol viewBox="0 0 16 16" id="folder" xmlns="http://www.w3.org/2000/svg"><path d="M7.228 5l-.475-1.335A1 1 0 0 0 5.81 3H2v9a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1H7.228zM13 3a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a2 2 0 0 1 2-2h3.81a3 3 0 0 1 2.827 1.995L13 3z"/></symbol><symbol viewBox="0 0 16 16" id="fork" xmlns="http://www.w3.org/2000/svg"><path d="M9 12.268a2 2 0 1 1-2 0V8.874A4.002 4.002 0 0 1 4 5V3.732a2 2 0 1 1 2 0V5a2 2 0 1 0 4 0V3.732a2 2 0 1 1 2 0V5a4.002 4.002 0 0 1-3 3.874v3.394zM11 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zM5 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 12a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="geo-nodes" xmlns="http://www.w3.org/2000/svg"><path d="M9.7 13.1l-.2.2c-.7.8-2 .9-2.8.1-.1 0-.1-.1-.1-.1l-.2-.2c-2 .2-3.4.7-3.4 1.4 0 .8 2.2 1.5 5 1.5s5-.7 5-1.5c0-.7-1.4-1.2-3.3-1.4M7.3 12.7c.4.4 1 .3 1.4-.1C11.6 9.5 13 7 13 5.3 13 2.4 10.8 0 8 0S3 2.4 3 5.3C3 7 4.4 9.5 7.3 12.7M8 2c1.6 0 3 1.4 3 3.3 0 1-1 2.8-3 5.2-2-2.4-3-4.2-3-5.2C5 3.4 6.4 2 8 2"/><circle cx="8" cy="5" r="1"/></symbol><symbol viewBox="0 0 16 16" id="git-merge" xmlns="http://www.w3.org/2000/svg"><path d="M11 12.268V5a1 1 0 0 0-1-1v1a.5.5 0 0 1-.8.4l-2.667-2a.5.5 0 0 1 0-.8L9.2.6a.5.5 0 0 1 .8.4v1a3 3 0 0 1 3 3v7.268a2 2 0 1 1-2 0zm-6 0a2 2 0 1 1-2 0V4.732a2 2 0 1 1 2 0v7.536zM4 4a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm0 11a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm8 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="group" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M3.048 11.997C-.377 11.975.013 11.782.013 10.56.013 9.235.653 8 4 8c.444 0 .84.022 1.194.062.164.435.426.82.76 1.132-1.786.389-2.721 1.353-2.906 2.803zm2.94-7.222a2.993 2.993 0 0 0-.976 1.95 2 2 0 1 1 .975-1.95zm6.964 7.222c-.185-1.45-1.12-2.414-2.906-2.803.334-.311.596-.697.76-1.132C11.16 8.022 11.556 8 12 8c3.346 0 3.987 1.235 3.987 2.56 0 1.222.39 1.415-3.035 1.437zm-1.964-5.272a2.993 2.993 0 0 0-.976-1.95 2 2 0 1 1 .976 1.95zM8 9a2 2 0 1 1 0-4 2 2 0 0 1 0 4zm0 5c-2.177 0-3.987-.115-3.987-1.44S4.653 10 8 10c3.346 0 3.987 1.235 3.987 2.56S10.177 14 8 14z"/></symbol><symbol viewBox="0 0 16 16" id="history" xmlns="http://www.w3.org/2000/svg"><path d="M2.868 3.24a7 7 0 1 1-.043 9.475 1 1 0 0 1 1.478-1.348 5 5 0 1 0 .124-6.865l.796.645a.5.5 0 0 1-.193.873l-3.232.814a.5.5 0 0 1-.622-.504L1.3 3a.5.5 0 0 1 .814-.37l.754.61zM9 8h1a1 1 0 0 1 0 2H8a.997.997 0 0 1-1-1V6a1 1 0 1 1 2 0v2z"/></symbol><symbol viewBox="0 0 16 16" id="home" xmlns="http://www.w3.org/2000/svg"><path d="M8.462 2.177a.505.505 0 0 1-.038.044l.038-.044zm-.787 0l.038.043a.5.5 0 0 1-.038-.043zM3.706 7h8.725L8.069 2.585 3.706 7zM7 13.369V12a1 1 0 0 1 2 0v1.369h3V9H4v4.369h3zM14 9v4.836c0 .833-.657 1.533-1.5 1.533h-9c-.843 0-1.5-.7-1.5-1.533V9h-.448a1.1 1.1 0 0 1-.783-1.873L6.934.887a1.5 1.5 0 0 1 2.269 0l6.165 6.24A1.1 1.1 0 0 1 14.585 9H14z"/></symbol><symbol viewBox="0 0 16 16" id="hook" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 3a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1h4zm0 1H6v1a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1V4zM7 8a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h2a3 3 0 0 1 3 3v2a3 3 0 0 1-3 3v4a2 2 0 1 0 4 0h-.44a.3.3 0 0 1-.25-.466l1.44-2.16a.3.3 0 0 1 .5 0l1.44 2.16a.3.3 0 0 1-.25.466H15a4 4 0 0 1-7 2.646A4 4 0 0 1 1 12H.56a.3.3 0 0 1-.25-.466l1.44-2.16a.3.3 0 0 1 .5 0l1.44 2.16a.3.3 0 0 1-.25.466H3a2 2 0 1 0 4 0V8z"/></symbol><symbol viewBox="0 0 16 16" id="issue-block" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M5.803 8a5.97 5.97 0 0 0-.462 1H4.5a.5.5 0 0 1 0-1h1.303zM4.5 5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1 0-1zm7.5.083a6.04 6.04 0 0 0-2 0V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h2.083a5.96 5.96 0 0 0 .72 2H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h6a3 3 0 0 1 3 3v2.083zm1.121 3.796zM11 16a5 5 0 1 1 0-10 5 5 0 0 1 0 10zm-1.293-2.292a3 3 0 0 0 4.001-4.001l-4.001 4zm-1.415-1.415l4.001-4a3 3 0 0 0-4.001 4.001z"/></symbol><symbol viewBox="0 0 16 16" id="issue-child" xmlns="http://www.w3.org/2000/svg"><path d="M11 8H5v1h1a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1h2V7a.997.997 0 0 1 1-1h3V4H4.5a.5.5 0 0 1-.5-.5v-2a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.5.5H9v2h3a.997.997 0 0 1 1 1v2h2a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1h-5a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1h1V8zm-9 3v2h3v-2H2zm9 0v2h3v-2h-3z"/></symbol><symbol viewBox="0 0 16 16" id="issue-close" xmlns="http://www.w3.org/2000/svg"><path d="M7.536 8.657l2.828-2.829a1 1 0 0 1 1.414 1.415l-3.535 3.535a.997.997 0 0 1-1.415 0l-2.12-2.121A1 1 0 0 1 6.12 7.243l1.415 1.414zM8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12z"/></symbol><symbol viewBox="0 0 16 16" id="issue-duplicate" xmlns="http://www.w3.org/2000/svg"><path d="M10.874 2H12a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3h-2c-.918 0-1.74-.413-2.29-1.063a3.987 3.987 0 0 0 1.988-.984A1 1 0 0 0 10 14h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1h-1V3c0-.345-.044-.68-.126-1zM4 0h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H4z"/></symbol><symbol viewBox="0 0 16 16" id="issue-new" xmlns="http://www.w3.org/2000/svg"><path d="M10 2V1a1 1 0 0 1 2 0v1h1a1 1 0 0 1 0 2h-1v1a1 1 0 0 1-2 0V4H9a1 1 0 1 1 0-2h1zm0 6a1 1 0 0 1 2 0v5a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3h1a1 1 0 1 1 0 2H5a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1V8z"/></symbol><symbol viewBox="0 0 16 16" id="issue-open" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zm0-2a4 4 0 1 1 0-8 4 4 0 0 1 0 8zm0-2a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"/></symbol><symbol viewBox="0 0 16 16" id="issue-open-m" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12z"/></symbol><symbol viewBox="0 0 16 16" id="issue-parent" xmlns="http://www.w3.org/2000/svg"><path d="M11 11H5v1h1.5a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.5.5h-6a.5.5 0 0 1-.5-.5v-2a.5.5 0 0 1 .5-.5H3v-2a.997.997 0 0 1 1-1h3V7H5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1H9v2h3a.997.997 0 0 1 1 1v2h2.5a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.5.5h-6a.5.5 0 0 1-.5-.5v-2a.5.5 0 0 1 .5-.5H11v-1zM6 3v2h4V3H6z"/></symbol><symbol viewBox="0 0 16 16" id="issues" xmlns="http://www.w3.org/2000/svg"><path d="M10.458 15.012l.311.055a3 3 0 0 0 3.476-2.433l1.389-7.879A3 3 0 0 0 13.2 1.28L11.23.933a3.002 3.002 0 0 0-.824-.031c.364.59.58 1.28.593 2.02l1.854.328a1 1 0 0 1 .811 1.158l-1.389 7.879a1 1 0 0 1-1.158.81l-.118-.02a3.98 3.98 0 0 1-.541 1.935zM3 0h4a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3z"/></symbol><symbol viewBox="0 0 16 16" id="key" xmlns="http://www.w3.org/2000/svg"><path d="M7.575 6.689a4.002 4.002 0 0 1 6.274-4.86 4 4 0 0 1-4.86 6.274l-2.21 2.21.706.708a1 1 0 1 1-1.414 1.414l-.707-.707-.707.707.707.707a1 1 0 1 1-1.414 1.414l-.707-.707a1 1 0 0 1-1.414-1.414l5.746-5.746zm2.032-.618a2 2 0 1 0 2.828-2.828A2 2 0 0 0 9.607 6.07z"/></symbol><symbol viewBox="0 0 16 16" id="key-2" xmlns="http://www.w3.org/2000/svg"><path d="M5.172 14.157l-.344.344-2.485.133a.462.462 0 0 1-.497-.503l.14-2.24a.599.599 0 0 1 .177-.382l5.155-5.155a4 4 0 1 1 2.828 2.828l-1.439 1.44-1.06-.354-.708.707.354 1.06-.707.708-1.06-.354-.708.707.354 1.06zm6.01-8.839a1 1 0 1 0 1.414-1.414 1 1 0 0 0-1.414 1.414z"/></symbol><symbol viewBox="0 0 16 16" id="label" xmlns="http://www.w3.org/2000/svg"><path d="M11.782 14.718a3 3 0 0 1-4.242 0L1.652 8.829a2 2 0 0 1-.565-1.702l.54-3.703a2 2 0 0 1 1.69-1.69l3.703-.54a2 2 0 0 1 1.703.564l5.888 5.888a3 3 0 0 1 0 4.243l-2.829 2.829zm1.415-5.657L7.309 3.173l-3.703.54-.54 3.702 5.888 5.888a1 1 0 0 0 1.414 0l2.829-2.828a1 1 0 0 0 0-1.414zM5.732 5.525A1 1 0 1 1 7.146 6.94a1 1 0 0 1-1.414-1.414z"/></symbol><symbol viewBox="0 0 16 16" id="labels" xmlns="http://www.w3.org/2000/svg"><path d="M9.424 2.254l2.08-.905a1 1 0 0 1 1.206.326l3.013 4.12a1 1 0 0 1 .16.849l-1.947 7.264a3 3 0 0 1-3.675 2.122l-.5-.135a3.999 3.999 0 0 0 1.082-1.782 1 1 0 0 0 1.16-.722l1.823-6.802-2.258-3.087-.687.299a2 2 0 0 0-.628-.88l-.829-.667zM.377 3.7L4.4.498a1 1 0 0 1 1.25.003L9.627 3.7a1 1 0 0 1 .373.78V13a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V4.482A1 1 0 0 1 .377 3.7zM2 13a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1V4.958L5.02 2.561 2 4.964V13zm3-6a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="leave" xmlns="http://www.w3.org/2000/svg"><path d="M11 7V5.883a.5.5 0 0 1 .757-.429l3.528 2.117a.5.5 0 0 1 0 .858l-3.528 2.117a.5.5 0 0 1-.757-.43V9H7a1 1 0 1 1 0-2h4zm-2 6.256a1 1 0 0 1 2 0A2.744 2.744 0 0 1 8.256 16H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h5.19A2.81 2.81 0 0 1 11 2.81a1 1 0 0 1-2 0A.81.81 0 0 0 8.19 2H3a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h5.256c.41 0 .744-.333.744-.744z"/></symbol><symbol viewBox="0 0 16 16" id="level-up" xmlns="http://www.w3.org/2000/svg"><path fill="#2E2E2E" fill-rule="evenodd" d="M7 6h3.489a.5.5 0 0 0 .373-.832L6.374.117a.5.5 0 0 0-.748 0l-4.488 5.05A.5.5 0 0 0 1.51 6H5v7a3 3 0 0 0 3 3h6a1 1 0 0 0 0-2H8a1 1 0 0 1-1-1V6z"/></symbol><symbol viewBox="0 0 16 16" id="license" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M12.56 8.9l2.66 4.606a.3.3 0 0 1-.243.45l-1.678.094a.1.1 0 0 0-.078.044l-.953 1.432a.3.3 0 0 1-.51-.016L9.097 10.9a5.994 5.994 0 0 0 3.464-2zm-5.23 2.063L4.707 15.51a.3.3 0 0 1-.51.016l-.953-1.432a.1.1 0 0 0-.078-.044l-1.678-.094a.3.3 0 0 1-.243-.45l2.48-4.297a5.983 5.983 0 0 0 3.607 1.754zM8 10A5 5 0 1 1 8 0a5 5 0 0 1 0 10zm0-2a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-1a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"/></symbol><symbol viewBox="0 0 16 16" id="link" xmlns="http://www.w3.org/2000/svg"><path d="M6.986 3.35l2.12-2.122a4 4 0 0 1 5.657 5.657l-2.828 2.829a4 4 0 0 1-5.657 0 1 1 0 0 1 1.414-1.415 2 2 0 0 0 2.829 0l2.828-2.828a2 2 0 1 0-2.828-2.828l-1.001 1a5.018 5.018 0 0 0-2.534-.294zm2.12 9.192l-2.12 2.121a4 4 0 1 1-5.658-5.656l2.829-2.829a4 4 0 0 1 5.657 0 1 1 0 1 1-1.415 1.414 2 2 0 0 0-2.828 0l-2.828 2.829a2 2 0 1 0 2.828 2.828l1.001-1.001a5.018 5.018 0 0 0 2.534.294z"/></symbol><symbol viewBox="0 0 16 16" id="list-bulleted" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M1 4a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm0 5a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4-7h10a1 1 0 0 1 0 2H5a1 1 0 1 1 0-2zm0 5h10a1 1 0 0 1 0 2H5a1 1 0 1 1 0-2zm-4 7a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4-2h10a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2z"/></symbol><symbol viewBox="0 0 16 16" id="list-numbered" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M6 2h8a1 1 0 0 1 0 2H6a1 1 0 1 1 0-2zm0 5h8a1 1 0 0 1 0 2H6a1 1 0 1 1 0-2zm0 5h8a1 1 0 0 1 0 2H6a1 1 0 0 1 0-2zM1.156 5v-.828h.816V2.204h-.72v-.636c.432-.084.708-.192.996-.372h.756v2.976h.684V5H1.156zm-.18 5v-.588c.9-.828 1.596-1.464 1.596-1.98 0-.342-.192-.504-.468-.504-.252 0-.444.18-.624.36l-.552-.552c.396-.42.756-.612 1.32-.612.768 0 1.308.492 1.308 1.248 0 .612-.576 1.284-1.092 1.812.192-.024.468-.048.636-.048h.636V10H.976zm1.26 5.072c-.618 0-1.068-.204-1.356-.54l.468-.648c.234.216.51.36.78.36.336 0 .552-.12.552-.36 0-.288-.15-.456-.948-.456v-.72c.636 0 .828-.168.828-.432 0-.228-.138-.348-.396-.348-.252 0-.432.108-.672.312l-.516-.624c.372-.312.768-.492 1.236-.492.84 0 1.38.384 1.38 1.074 0 .366-.204.642-.612.822v.024c.432.132.732.432.732.912 0 .72-.684 1.116-1.476 1.116z"/></symbol><symbol viewBox="0 0 16 16" id="location" xmlns="http://www.w3.org/2000/svg"><path d="M8.755 15.144a1 1 0 0 1-1.51 0C3.748 11.114 2 8.065 2 6a6 6 0 1 1 12 0c0 2.065-1.748 5.113-5.245 9.144zM12 6a4 4 0 1 0-8 0c0 1.314 1.312 3.71 4 6.944C10.688 9.71 12 7.314 12 6zM8 8a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"/></symbol><symbol viewBox="0 0 16 16" id="location-dot" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M6.314 13.087C4.382 13.295 3 13.85 3 14.5c0 .828 2.239 1.5 5 1.5s5-.672 5-1.5c0-.65-1.382-1.205-3.314-1.413l-.202.225a2 2 0 0 1-2.968 0l-.202-.225zm2.428-.445a1 1 0 0 1-1.484 0C4.419 9.5 3 7.037 3 5.252 3 2.353 5.239 0 8 0s5 2.352 5 5.253c0 1.784-1.42 4.247-4.258 7.389zM11 5.252C11 3.436 9.634 2 8 2S5 3.435 5 5.253c0 1.027.974 2.824 3 5.203 2.026-2.38 3-4.176 3-5.203zM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="lock" xmlns="http://www.w3.org/2000/svg"><path d="M10 5V4h2v1a3 3 0 0 1 3 3v5a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V8a3 3 0 0 1 3-3V4h2v1h4zM4 7a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V8a1 1 0 0 0-1-1H4zm0-3a4 4 0 1 1 8 0h-2a2 2 0 1 0-4 0H4z"/></symbol><symbol viewBox="0 0 16 16" id="lock-open" xmlns="http://www.w3.org/2000/svg"><path d="M4.044 4a4 4 0 0 1 6.99-2.658 1 1 0 1 1-1.495 1.33A2 2 0 0 0 6.044 4a.998.998 0 0 1-.07.367v.701H12a3 3 0 0 1 3 3v5a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3v-5a3 3 0 0 1 2.974-3V4h.07zM4 7.07a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-5a1 1 0 0 0-1-1H4z"/></symbol><symbol viewBox="0 0 16 16" id="log" xmlns="http://www.w3.org/2000/svg"><path d="M4 0h8a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H4zm1 4a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm0 3a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3-5h3a1 1 0 0 1 0 2H8a1 1 0 1 1 0-2zm0 3h3a1 1 0 0 1 0 2H8a1 1 0 1 1 0-2zm-3 5a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3-2h3a1 1 0 0 1 0 2H8a1 1 0 0 1 0-2z"/></symbol><symbol viewBox="0 0 16 16" id="mail" xmlns="http://www.w3.org/2000/svg"><path d="M14 5.6L9.338 9.796a2 2 0 0 1-2.676 0L2 5.6V11a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V5.6zM3 2h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3zm.212 2L8 8.31 12.788 4H3.212z"/></symbol><symbol viewBox="0 0 16 16" id="merge-request-close" xmlns="http://www.w3.org/2000/svg"><path d="M9.414 8l1.414 1.414a1 1 0 1 1-1.414 1.414L8 9.414l-1.414 1.414a1 1 0 1 1-1.414-1.414L6.586 8 5.172 6.586a1 1 0 1 1 1.414-1.414L8 6.586l1.414-1.414a1 1 0 1 1 1.414 1.414L9.414 8zM8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12z"/></symbol><symbol viewBox="0 0 16 16" id="merge-request-close-m" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M9.414 8l4.95-4.95a1 1 0 0 0-1.414-1.414L8 6.586l-4.95-4.95A1 1 0 0 0 1.636 3.05L6.586 8l-4.95 4.95a1 1 0 1 0 1.414 1.414L8 9.414l4.95 4.95a1 1 0 1 0 1.414-1.414L9.414 8z"/></symbol><symbol viewBox="0 0 16 16" id="messages" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8.588 8.942l1.173 5.862A1 1 0 0 1 8.78 16H7.22a1 1 0 0 1-.98-1.196l1.172-5.862a3.014 3.014 0 0 0 1.176 0zM8 8a2 2 0 1 1 0-4 2 2 0 0 1 0 4zM4.464 2.464L5.88 3.88a3 3 0 0 0 0 4.242L4.464 9.536a5 5 0 0 1 0-7.072zm7.072 7.072L10.12 8.12a3 3 0 0 0 0-4.242l1.415-1.415a5 5 0 0 1 0 7.072zM2.343.343l1.414 1.414a6 6 0 0 0 0 8.486l-1.414 1.414a8 8 0 0 1 0-11.314zm11.314 11.314l-1.414-1.414a6 6 0 0 0 0-8.486L13.657.343a8 8 0 0 1 0 11.314z"/></symbol><symbol viewBox="0 0 16 16" id="mobile-issue-close" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M5.657 10.728L2.12 7.192A1 1 0 1 0 .707 8.607l4.243 4.242a.997.997 0 0 0 1.414 0l8.485-8.485a1 1 0 1 0-1.414-1.414l-7.778 7.778z"/></symbol><symbol viewBox="0 0 16 16" id="monitor" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 13v1h3a1 1 0 0 1 0 2H3a1 1 0 0 1 0-2h3v-1H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v7a3 3 0 0 1-3 3h-3zM3 2a1 1 0 0 0-1 1v7a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3zm5.723 6.416l-2.66-1.773-1.71 1.71a.5.5 0 1 1-.707-.707l2-2a.5.5 0 0 1 .631-.062l2.66 1.773 2.71-2.71a.5.5 0 0 1 .707.707l-3 3a.5.5 0 0 1-.631.062z"/></symbol><symbol viewBox="0 0 16 16" id="more" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8 4a2 2 0 1 1 0-4 2 2 0 0 1 0 4zm0 6a2 2 0 1 1 0-4 2 2 0 0 1 0 4zm0 6a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"/></symbol><symbol viewBox="0 0 16 16" id="notifications" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M6 14H2.435a2 2 0 0 1-1.761-2.947c.962-1.788 1.521-3.065 1.68-3.832.322-1.566.947-5.501 4.65-6.134a1 1 0 1 1 1.994-.024c3.755.528 4.375 4.27 4.761 6.043.188.86.742 2.188 1.661 3.982A2 2 0 0 1 13.64 14H10a2 2 0 1 1-4 0zm5.805-6.468c-.325-1.492-.37-1.674-.61-2.288C10.6 3.716 9.742 3 8.07 3c-1.608 0-2.49.718-3.103 2.197-.28.676-.356.982-.654 2.428-.208 1.012-.827 2.424-1.877 4.375H13.64c-.993-1.937-1.6-3.396-1.835-4.468z"/></symbol><symbol viewBox="0 0 16 16" id="notifications-off" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M13.26 5.089c.243.757.382 1.478.5 2.017.187.86.74 2.188 1.66 3.982A2 2 0 0 1 13.64 14H10a2 2 0 1 1-4 0H4.35l2-2h7.29c-.993-1.937-1.6-3.396-1.835-4.468-.07-.326-.129-.59-.178-.81l1.634-1.633zM10.943 1.75l-1.48 1.48C9.07 3.076 8.612 3 8.069 3c-1.608 0-2.49.718-3.103 2.197-.28.676-.356.982-.654 2.428-.065.317-.17.673-.317 1.073L.45 12.242a1.99 1.99 0 0 1 .224-1.19c.962-1.787 1.521-3.064 1.68-3.831.322-1.566.947-5.501 4.65-6.134a1 1 0 1 1 1.994-.024 4.867 4.867 0 0 1 1.944.688zm2.932-.105a1 1 0 0 1 0 1.415L2.561 14.374a1 1 0 1 1-1.415-1.414L12.46 1.646a1 1 0 0 1 1.414 0z"/></symbol><symbol viewBox="0 0 16 16" id="overview" xmlns="http://www.w3.org/2000/svg"><path d="M2 0h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2zm0 2v3h3V2H2zm9-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2h-3a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2zm0 2v3h3V2h-3zM2 9h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2zm0 2v3h3v-3H2zm9-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2h-3a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2zm0 2v3h3v-3h-3z"/></symbol><symbol viewBox="0 0 16 16" id="pencil" xmlns="http://www.w3.org/2000/svg"><path d="M13.02 1.293l1.414 1.414a1 1 0 0 1 0 1.414L4.119 14.436a1 1 0 0 1-.704.293l-2.407.008L1 12.316a1 1 0 0 1 .293-.71L11.605 1.292a1 1 0 0 1 1.414 0zm-1.416 1.415l-.707.707L12.31 4.83l.707-.707-1.414-1.415zM3.411 13.73l1.123-1.122H3.12v-1.415L2 12.312l.005 1.422 1.406-.005z"/></symbol><symbol viewBox="0 0 16 16" id="pipeline" xmlns="http://www.w3.org/2000/svg"><path d="M8.969 7.25a2 2 0 1 1-1.938 0A1.002 1.002 0 0 1 7 7V5.083a.2.2 0 0 1 .06-.142l.877-.87a.1.1 0 0 1 .141 0l.864.87A.2.2 0 0 1 9 5.083V7c0 .086-.01.17-.031.25zM8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zm4.5-4a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm0-3a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm-2 6a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm0-9a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm-5 9a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm0-9a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm-2 6a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm0-3a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zM8 10a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="play" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M2.765 15.835c-.545.321-1.258.159-1.593-.363A1.075 1.075 0 0 1 1 14.89V1.11C1 .496 1.518 0 2.158 0c.214 0 .424.057.607.165l11.684 6.89c.544.321.714 1.005.38 1.526a1.135 1.135 0 0 1-.38.364l-11.684 6.89z"/></symbol><symbol viewBox="0 0 16 16" id="plus" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7 7V1a1 1 0 1 1 2 0v6h6a1 1 0 0 1 0 2H9v6a1 1 0 0 1-2 0V9H1a1 1 0 1 1 0-2h6z"/></symbol><symbol viewBox="0 0 16 16" id="plus-square" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M9 7V4a1 1 0 1 0-2 0v3H4a1 1 0 1 0 0 2h3v3a1 1 0 0 0 2 0V9h3a1 1 0 0 0 0-2H9zM3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3z"/></symbol><symbol viewBox="0 0 16 16" id="plus-square-o" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7 7V5a1 1 0 1 1 2 0v2h2a1 1 0 0 1 0 2H9v2a1 1 0 0 1-2 0V9H5a1 1 0 1 1 0-2h2zM3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3z"/></symbol><symbol viewBox="0 0 16 16" id="preferences" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M5 12h10a1 1 0 0 1 0 2H5a1 1 0 0 1-2 0v-2a1 1 0 0 1 2 0zm-3 0H1a1 1 0 0 0 0 2h1v-2zm11-5h2a1 1 0 0 1 0 2h-2a1 1 0 0 1-2 0V7a1 1 0 0 1 2 0zm-3 0H1a1 1 0 1 0 0 2h9V7zM6 2h9a1 1 0 0 1 0 2H6a1 1 0 1 1-2 0V2a1 1 0 1 1 2 0zM3 2H1a1 1 0 1 0 0 2h2V2z"/></symbol><symbol viewBox="0 0 16 16" id="profile" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zm-4.274-3.404C4.412 9.709 5.694 9 8 9c2.313 0 3.595.7 4.28 1.586A4.997 4.997 0 0 1 8 13a4.997 4.997 0 0 1-4.274-2.404zM8 8a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"/></symbol><symbol viewBox="0 0 16 16" id="project" xmlns="http://www.w3.org/2000/svg"><path d="M8.462 2.177l-.038.044a.505.505 0 0 0 .038-.044zm-.787 0a.5.5 0 0 0 .038.043l-.038-.043zM3.706 7h8.725L8.069 2.585 3.706 7zM7 13.369V12a1 1 0 0 1 2 0v1.369h3V9H4v4.369h3zM14 9v4.836c0 .833-.657 1.533-1.5 1.533h-9c-.843 0-1.5-.7-1.5-1.533V9h-.448a1.1 1.1 0 0 1-.783-1.873L6.934.887a1.5 1.5 0 0 1 2.269 0l6.165 6.24A1.1 1.1 0 0 1 14.585 9H14z"/></symbol><symbol viewBox="0 0 16 16" id="push-rules" xmlns="http://www.w3.org/2000/svg"><path d="M6.268 9a2 2 0 0 1 3.464 0H11a1 1 0 0 1 0 2H9.732a2 2 0 0 1-3.464 0H5a1 1 0 0 1 0-2h1.268zM7 2H4a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1h-1v3.515a.3.3 0 0 1-.434.268l-1.432-.716a.3.3 0 0 0-.268 0l-1.432.716A.3.3 0 0 1 7 5.515V2zM4 0h8a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm4 11a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="question" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm-1.46-5.602h2.233a3.97 3.97 0 0 1 .051-.558c.029-.17.073-.326.133-.469.06-.143.14-.28.242-.41.102-.13.228-.263.38-.399.26-.24.504-.467.733-.683a5.03 5.03 0 0 0 .598-.668c.17-.23.302-.477.399-.742a2.66 2.66 0 0 0 .144-.907c0-.505-.083-.95-.25-1.335a2.55 2.55 0 0 0-.723-.97 3.2 3.2 0 0 0-1.152-.589 5.441 5.441 0 0 0-1.531-.2c-.516 0-.998.063-1.445.188a3.19 3.19 0 0 0-1.168.59c-.331.268-.594.61-.79 1.027-.195.417-.295.917-.3 1.5h2.64c.006-.224.04-.416.102-.578.062-.161.142-.293.238-.394a.921.921 0 0 1 .332-.227 1.04 1.04 0 0 1 .39-.074c.34 0 .593.095.763.285.169.19.254.488.254.895 0 .328-.106.63-.317.906-.21.276-.499.565-.863.867-.214.182-.39.374-.531.574-.141.2-.253.42-.336.657a3.656 3.656 0 0 0-.176.777 7.89 7.89 0 0 0-.05.937zm-.321 2.375c0 .188.035.362.105.524.07.161.17.3.301.418.13.117.284.21.46.277.178.068.376.102.595.102.218 0 .416-.034.593-.102.178-.068.331-.16.461-.277a1.2 1.2 0 0 0 .301-.418c.07-.162.106-.336.106-.524a1.3 1.3 0 0 0-.106-.523 1.2 1.2 0 0 0-.3-.418 1.461 1.461 0 0 0-.462-.277 1.651 1.651 0 0 0-.593-.102c-.22 0-.417.034-.594.102a1.46 1.46 0 0 0-.461.277 1.2 1.2 0 0 0-.3.418 1.284 1.284 0 0 0-.106.523z"/></symbol><symbol viewBox="0 0 16 16" id="question-o" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zm-.778-4.151c0-.301.014-.575.044-.82a3.2 3.2 0 0 1 .154-.68c.073-.208.17-.4.294-.575.123-.176.278-.343.465-.503a4.81 4.81 0 0 0 .755-.758c.185-.242.277-.506.277-.793 0-.356-.074-.617-.222-.783-.148-.166-.37-.25-.667-.25a.92.92 0 0 0-.342.065.806.806 0 0 0-.29.199 1.04 1.04 0 0 0-.209.345 1.5 1.5 0 0 0-.088.506H5.082c.005-.51.092-.948.263-1.313.171-.364.401-.664.69-.899.29-.234.63-.406 1.023-.516a4.66 4.66 0 0 1 1.264-.164c.497 0 .944.058 1.34.174.397.117.733.289 1.008.517.276.227.487.51.633.847.146.337.218.727.218 1.17 0 .295-.042.56-.126.792a2.52 2.52 0 0 1-.349.65 4.4 4.4 0 0 1-.523.584c-.2.19-.414.389-.642.598a2.73 2.73 0 0 0-.332.349c-.089.114-.16.233-.212.359a1.868 1.868 0 0 0-.116.41 3.39 3.39 0 0 0-.044.489H7.222zm-.28 2.078c0-.164.03-.317.092-.458a1.05 1.05 0 0 1 .263-.366c.114-.103.248-.183.403-.243a1.45 1.45 0 0 1 .52-.089c.191 0 .364.03.52.09.154.059.289.14.403.242.114.103.201.224.263.366.061.141.092.294.092.458 0 .164-.03.316-.092.458a1.05 1.05 0 0 1-.263.365 1.278 1.278 0 0 1-.404.243 1.43 1.43 0 0 1-.52.089c-.19 0-.364-.03-.519-.089-.155-.06-.29-.14-.403-.243a1.05 1.05 0 0 1-.263-.365 1.135 1.135 0 0 1-.093-.458z"/></symbol><symbol viewBox="0 0 16 16" id="quote" xmlns="http://www.w3.org/2000/svg"><path d="M15 3v8a3 3 0 0 1-3 3 1 1 0 0 1 0-2 1 1 0 0 0 1-1V9h-2a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h3a1 1 0 0 1 1 1zM7 3v8a3 3 0 0 1-3 3 1 1 0 0 1 0-2 1 1 0 0 0 1-1V9H3a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h3a1 1 0 0 1 1 1z"/></symbol><symbol viewBox="0 0 16 16" id="redo" xmlns="http://www.w3.org/2000/svg"><path d="M4.666 4.423a5 5 0 1 1-.203 6.944 1 1 0 1 0-1.478 1.347 7 7 0 1 0 .12-9.556L1.842 2.137a.5.5 0 0 0-.815.385L1 7.26a.5.5 0 0 0 .607.492l4.629-1.013a.5.5 0 0 0 .207-.877L4.666 4.423z"/></symbol><symbol viewBox="0 0 16 16" id="remove" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M2 3a1 1 0 1 1 0-2h12a1 1 0 0 1 0 2v10a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V3zm3-2a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1H5zM4 3v10a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V3H4zm2.5 2a.5.5 0 0 1 .5.5v6a.5.5 0 1 1-1 0v-6a.5.5 0 0 1 .5-.5zm3 0a.5.5 0 0 1 .5.5v6a.5.5 0 1 1-1 0v-6a.5.5 0 0 1 .5-.5z"/></symbol><symbol viewBox="0 0 16 16" id="repeat" xmlns="http://www.w3.org/2000/svg"><path d="M11.494 4.423a5 5 0 1 0 .203 6.944 1 1 0 1 1 1.478 1.347 7 7 0 1 1-.12-9.556l1.262-1.021a.5.5 0 0 1 .815.385l.028 4.738a.5.5 0 0 1-.607.492L9.924 6.739a.5.5 0 0 1-.207-.877l1.777-1.439z"/></symbol><symbol viewBox="0 0 16 16" id="retry" xmlns="http://www.w3.org/2000/svg"><path d="M4.009 6.958a4 4 0 0 0 5.283 4.775 1 1 0 0 1 .712 1.87A6 6 0 0 1 2.077 6.44l-.741-.2a.5.5 0 0 1-.12-.915L3.41 4.058a.5.5 0 0 1 .683.183l1.268 2.196a.5.5 0 0 1-.563.733l-.79-.212zm7.777 2.084a4 4 0 0 0-5.284-4.775 1 1 0 0 1-.711-1.87 6 6 0 0 1 7.927 7.162l.74.2a.5.5 0 0 1 .121.915l-2.196 1.268a.5.5 0 0 1-.683-.183l-1.267-2.196a.5.5 0 0 1 .562-.733l.79.212z"/></symbol><symbol viewBox="0 0 16 16" id="scale" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M13.99 9a.792.792 0 0 0-.078-.231L13 7l-.912 1.769a.791.791 0 0 0-.077.231h1.978zm-10 0a.792.792 0 0 0-.078-.231L3 7l-.912 1.769A.791.791 0 0 0 2.011 9h1.978zM2 0h12a1 1 0 0 1 0 2H2a1 1 0 1 1 0-2zm3 14h6a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2zM8 4a1 1 0 0 1 1 1v9H7V5a1 1 0 0 1 1-1zm-4.53-.714l2.265 4.735c.68 1.42.006 3.091-1.504 3.73A3.161 3.161 0 0 1 3 12c-1.657 0-3-1.263-3-2.821 0-.4.09-.794.264-1.158L2.53 3.286a.53.53 0 0 1 .94 0zm10 0l2.265 4.735c.68 1.42.006 3.091-1.504 3.73A3.161 3.161 0 0 1 13 12c-1.657 0-3-1.263-3-2.821 0-.4.09-.794.264-1.158l2.266-4.735a.53.53 0 0 1 .94 0z"/></symbol><symbol viewBox="0 0 16 16" id="screen-full" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M14 14v-2a1 1 0 0 1 2 0v3a.997.997 0 0 1-1 1h-3a1 1 0 0 1 0-2h2zM2 14v-2a1 1 0 0 0-2 0v3a1 1 0 0 0 1 1h3a1 1 0 0 0 0-2H2zM15.707.293A.997.997 0 0 1 16 1v3a1 1 0 0 1-2 0V2h-2a1 1 0 0 1 0-2h3c.276 0 .526.112.707.293zM2 2v2a1 1 0 1 1-2 0V1a.997.997 0 0 1 1-1h3a1 1 0 1 1 0 2H2zm4 4h4a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1z"/></symbol><symbol viewBox="0 0 16 16" id="screen-normal" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M3 3V1a1 1 0 1 1 2 0v3a.997.997 0 0 1-1 1H1a1 1 0 1 1 0-2h2zm10 0h2a1 1 0 0 1 0 2h-3a.997.997 0 0 1-1-1V1a1 1 0 0 1 2 0v2zM3 13H1a1 1 0 0 1 0-2h3a.997.997 0 0 1 1 1v3a1 1 0 0 1-2 0v-2zm10 0v2a1 1 0 0 1-2 0v-3a.997.997 0 0 1 1-1h3a1 1 0 0 1 0 2h-2zM6.5 7h3a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5z"/></symbol><symbol viewBox="0 0 16 16" id="search" xmlns="http://www.w3.org/2000/svg"><path d="M8.853 8.854a3.5 3.5 0 1 0-4.95-4.95 3.5 3.5 0 0 0 4.95 4.95zm.207 2.328a5.5 5.5 0 1 1 2.121-2.121l3.329 3.328a1.5 1.5 0 0 1-2.121 2.121L9.06 11.182z"/></symbol><symbol viewBox="0 0 16 16" id="settings" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M2.415 5.803L1.317 4.084A.5.5 0 0 1 1.35 3.5l.805-.994a.5.5 0 0 1 .564-.153l1.878.704a5.975 5.975 0 0 1 1.65-.797L6.885.342A.5.5 0 0 1 7.36 0h1.28a.5.5 0 0 1 .474.342l.639 1.918a5.97 5.97 0 0 1 1.65.797l1.877-.704a.5.5 0 0 1 .565.153l.805.994a.5.5 0 0 1 .032.584l-1.097 1.719c.217.551.354 1.143.399 1.76l1.731 1.058a.5.5 0 0 1 .227.54l-.288 1.246a.5.5 0 0 1-.44.385l-2.008.19a6.026 6.026 0 0 1-1.142 1.431l.265 1.995a.5.5 0 0 1-.277.516l-1.15.56a.5.5 0 0 1-.576-.1l-1.424-1.452a6.047 6.047 0 0 1-1.804 0l-1.425 1.453a.5.5 0 0 1-.576.1l-1.15-.561a.5.5 0 0 1-.276-.516l.265-1.995a6.026 6.026 0 0 1-1.143-1.43l-2.008-.191a.5.5 0 0 1-.44-.385L.058 9.16a.5.5 0 0 1 .226-.539l1.732-1.058a5.968 5.968 0 0 1 .399-1.76zM8 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/></symbol><symbol viewBox="0 0 16 16" id="shield" xmlns="http://www.w3.org/2000/svg"><path d="M4 0h8a3 3 0 0 1 3 3v7.186a3 3 0 0 1-1.426 2.554l-4 2.465a3 3 0 0 1-3.148 0l-4-2.465A3 3 0 0 1 1 10.186V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v7.186a1 1 0 0 0 .475.852l4 2.464a1 1 0 0 0 1.05 0l4-2.464a1 1 0 0 0 .475-.852V3a1 1 0 0 0-1-1H4zm0 1.5a.5.5 0 0 1 .5-.5h4v8.837a.5.5 0 0 1-.753.431l-3.5-2.052A.5.5 0 0 1 4 9.785V3.5z"/></symbol><symbol viewBox="0 0 16 16" id="slight-frown" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zm-2.163-3.275a2.499 2.499 0 0 1 4.343.03.5.5 0 0 1-.871.49 1.5 1.5 0 0 0-2.607-.018.5.5 0 1 1-.865-.502zM5 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm6 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="slight-smile" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zM5 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm6 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm-5.163 2.254a.5.5 0 1 1 .865-.502 1.499 1.499 0 0 0 2.607-.018.5.5 0 1 1 .871.49 2.499 2.499 0 0 1-4.343.03z"/></symbol><symbol viewBox="0 0 16 16" id="smile" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zM6.18 6.27a.5.5 0 0 1-.873.487.5.5 0 0 0-.872-.003.5.5 0 1 1-.87-.495 1.5 1.5 0 0 1 2.616.012zm6 0a.5.5 0 1 1-.873.487.5.5 0 0 0-.872-.003.5.5 0 1 1-.87-.495 1.5 1.5 0 0 1 2.616.012zM5 9a3 3 0 0 0 6 0H5z"/></symbol><symbol viewBox="0 0 16 16" id="smiley" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zM5 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm6 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zM5 9h6a3 3 0 0 1-6 0z"/></symbol><symbol viewBox="0 0 16 16" id="snippet" xmlns="http://www.w3.org/2000/svg"><path d="M10.67 9.31a3.001 3.001 0 0 1 2.062 5.546 3 3 0 0 1-3.771-4.559 1.007 1.007 0 0 1-.095-.137l-4.5-7.794a1 1 0 0 1 1.732-1l4.5 7.794c.028.05.052.1.071.15zm-3.283.35l-.289.5c-.028.05-.06.095-.095.137a3.001 3.001 0 0 1-3.77 4.56A3 3 0 0 1 5.294 9.31c.02-.051.043-.102.071-.15l.866-1.5 1.155 2zm2.31-4l-1.156-2 1.325-2.294a1 1 0 0 1 1.732 1L9.696 5.66zm-5.465 7.464a1 1 0 1 0 1-1.732 1 1 0 0 0-1 1.732zm7.5 0a1 1 0 1 0-1-1.732 1 1 0 0 0 1 1.732z"/></symbol><symbol viewBox="0 0 16 16" id="spam" xmlns="http://www.w3.org/2000/svg"><path d="M8.75.433l5.428 3.134a1.5 1.5 0 0 1 .75 1.299v6.268a1.5 1.5 0 0 1-.75 1.299L8.75 15.567a1.5 1.5 0 0 1-1.5 0l-5.428-3.134a1.5 1.5 0 0 1-.75-1.299V4.866a1.5 1.5 0 0 1 .75-1.299L7.25.433a1.5 1.5 0 0 1 1.5 0zM3.072 5.155v5.69L8 13.691l4.928-2.846v-5.69L8 2.309 3.072 5.155zM8 4a1 1 0 0 1 1 1v3a1 1 0 1 1-2 0V5a1 1 0 0 1 1-1zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="star" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7.609 14.394l-3.465 1.473a1 1 0 0 1-1.39-.989l.276-4.024a1 1 0 0 0-.219-.694L.303 7.037A1 1 0 0 1 .83 5.443l3.715-.964a1 1 0 0 0 .609-.457L7.14.682a1 1 0 0 1 1.72 0l1.985 3.34a1 1 0 0 0 .609.457l3.715.964a1 1 0 0 1 .528 1.594L13.19 10.16a1 1 0 0 0-.219.694l.275 4.024a1 1 0 0 1-1.389.989l-3.465-1.473a1 1 0 0 0-.782 0z"/></symbol><symbol viewBox="0 0 16 16" id="star-o" xmlns="http://www.w3.org/2000/svg"><path d="M10.975 10.99a3 3 0 0 1 .655-2.083l1.54-1.916-2.219-.576a3 3 0 0 1-1.825-1.37L8 3.15 6.874 5.044a3 3 0 0 1-1.825 1.371l-2.218.576 1.54 1.916a3 3 0 0 1 .654 2.083l-.165 2.4 1.965-.836a3 3 0 0 1 2.348 0l1.965.836-.164-2.399zM7.61 14.394l-3.465 1.473a1 1 0 0 1-1.39-.989l.276-4.024a1 1 0 0 0-.219-.694L.303 7.037A1 1 0 0 1 .83 5.443l3.715-.964a1 1 0 0 0 .609-.457L7.14.682a1 1 0 0 1 1.72 0l1.985 3.34a1 1 0 0 0 .609.457l3.715.964a1 1 0 0 1 .528 1.594L13.19 10.16a1 1 0 0 0-.219.694l.275 4.024a1 1 0 0 1-1.389.989l-3.465-1.473a1 1 0 0 0-.782 0z"/></symbol><symbol viewBox="0 0 16 16" id="stop" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M2 0h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2z"/></symbol><symbol viewBox="0 0 16 16" id="talic" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M6 0h7a1 1 0 0 1 0 2H6a1 1 0 1 1 0-2zm2 2h3L8 14H5L8 2zM3 14h7a1 1 0 0 1 0 2H3a1 1 0 0 1 0-2z"/></symbol><symbol viewBox="0 0 16 16" id="task-done" xmlns="http://www.w3.org/2000/svg"><path d="M7.536 8.657l2.828-2.829a1 1 0 0 1 1.414 1.415l-3.535 3.535a.997.997 0 0 1-1.415 0l-2.12-2.121A1 1 0 0 1 6.12 7.243l1.415 1.414zM3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3z"/></symbol><symbol viewBox="0 0 16 16" id="template" xmlns="http://www.w3.org/2000/svg"><path d="M3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3zm.8 2h2.4a.8.8 0 0 1 .8.8v1.4a.8.8 0 0 1-.8.8H3.8a.8.8 0 0 1-.8-.8V4.8a.8.8 0 0 1 .8-.8zm4.7 0h4a.5.5 0 1 1 0 1h-4a.5.5 0 0 1 0-1zm0 2h4a.5.5 0 1 1 0 1h-4a.5.5 0 0 1 0-1zm-5 3h9a.5.5 0 1 1 0 1h-9a.5.5 0 0 1 0-1zm0 2h9a.5.5 0 1 1 0 1h-9a.5.5 0 1 1 0-1z"/></symbol><symbol viewBox="0 0 16 16" id="thump-down" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8.33 11h5.282a2 2 0 0 0 1.963-2.38l-.563-2.905a3 3 0 0 0-.243-.732l-1.103-2.286A3 3 0 0 0 10.964 1H7a3 3 0 0 0-3 3v6.3a2 2 0 0 0 .436 1.247l3.11 3.9a.632.632 0 0 0 .941.053l.137-.137a1 1 0 0 0 .28-.87L8.329 11zM1 10h2V3H1a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1z"/></symbol><symbol viewBox="0 0 16 16" id="thump-up" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8.33 5h5.282a2 2 0 0 1 1.963 2.38l-.563 2.905a3 3 0 0 1-.243.732l-1.103 2.286A3 3 0 0 1 10.964 15H7a3 3 0 0 1-3-3V5.7a2 2 0 0 1 .436-1.247l3.11-3.9A.632.632 0 0 1 8.487.5l.137.137a1 1 0 0 1 .28.87L8.329 5zM1 6h2v7H1a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1z"/></symbol><symbol viewBox="0 0 16 16" id="timer" xmlns="http://www.w3.org/2000/svg"><path d="M12.022 3.27l.77-.77a1 1 0 0 1 1.415 1.414l-.728.729a7 7 0 1 1-1.456-1.372zM8 14A5 5 0 1 0 8 4a5 5 0 0 0 0 10zm0-9a1 1 0 0 1 1 1v2a1 1 0 1 1-2 0V6a1 1 0 0 1 1-1zM6 0h4a1 1 0 0 1 0 2H6a1 1 0 1 1 0-2z"/></symbol><symbol viewBox="0 0 16 16" id="todo-add" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 4V2a1 1 0 0 1 2 0v2h2a1 1 0 0 1 0 2h-2v2a1 1 0 0 1-2 0V6H8a1 1 0 1 1 0-2h2zm2 7a1 1 0 0 1 2 0v2a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3h2a1 1 0 1 1 0 2H3a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-2z"/></symbol><symbol viewBox="0 0 16 16" id="todo-done" xmlns="http://www.w3.org/2000/svg"><path d="M8.243 7.485l4.95-4.95a1 1 0 1 1 1.414 1.415L8.95 9.607a.997.997 0 0 1-1.414 0L4.707 6.778a1 1 0 0 1 1.414-1.414l2.122 2.121zM12 11a1 1 0 0 1 2 0v2a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3h2a1 1 0 1 1 0 2H3a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-2z"/></symbol><symbol viewBox="0 0 16 16" id="token" xmlns="http://www.w3.org/2000/svg"><path d="M3 2h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H3zm1 5a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="unapproval" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M11.95 8.536l1.06-1.061a1 1 0 0 1 1.415 1.414l-1.061 1.06 1.06 1.061a1 1 0 0 1-1.414 1.415l-1.06-1.061-1.06 1.06a1 1 0 1 1-1.415-1.414l1.06-1.06-1.06-1.06a1 1 0 0 1 1.414-1.415l1.06 1.06zm-3.768-.33c.006.503.201 1.006.586 1.39l.353.354-.353.353a2 2 0 1 0 2.828 2.829l.354-.354.047.048C11.964 14.363 11.527 15 6 15c-5.924 0-6-.78-6-2.52S.964 8 6 8c.834 0 1.557.074 2.182.205zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6z"/></symbol><symbol viewBox="0 0 16 16" id="unassignee" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M11 5h4a1 1 0 0 1 0 2h-4a1 1 0 0 1 0-2zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6zM6 15c-5.924 0-6-.78-6-2.52S.964 8 6 8s6 2.692 6 4.48c0 1.788-.076 2.52-6 2.52z"/></symbol><symbol viewBox="0 0 16 16" id="unlink" xmlns="http://www.w3.org/2000/svg"><path d="M11.295 8.845l-.659-1.664a1.78 1.78 0 0 0 .04-.04l1.415-1.414c.586-.586.654-1.468.152-1.97s-1.384-.434-1.97.152L8.859 5.323a1.781 1.781 0 0 0-.04.04l-1.664-.658c.141-.208.305-.408.491-.594l1.415-1.414c1.366-1.367 3.424-1.525 4.596-.354 1.171 1.172 1.013 3.23-.354 4.596L11.89 8.354c-.186.186-.386.35-.594.491zm-2.45 2.45a4.075 4.075 0 0 1-.491.594l-1.415 1.414c-1.366 1.367-3.424 1.525-4.596.354-1.171-1.172-1.013-3.23.354-4.596L4.11 7.646c.186-.186.386-.35.594-.491l.659 1.664a1.781 1.781 0 0 0-.04.04l-1.415 1.414c-.586.586-.654 1.468-.152 1.97s1.384.434 1.97-.152l1.414-1.414a1.78 1.78 0 0 0 .04-.04l1.664.658zm3.812-2.088h2a.5.5 0 0 1 .5.5v.05a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-.05a.5.5 0 0 1 .5-.5zm-.384 2.116l1.415 1.414a.5.5 0 0 1 0 .708l-.037.036a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 0-.707l.036-.037a.5.5 0 0 1 .707 0zm-2.823 1.09a.5.5 0 0 1 .5-.5h.052a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.5.5H9.95a.5.5 0 0 1-.5-.5v-2zm-2.748-9.16a.5.5 0 0 1-.5.5h-.05a.5.5 0 0 1-.5-.5v-2a.5.5 0 0 1 .5-.5h.05a.5.5 0 0 1 .5.5v2zm-2.116.383a.5.5 0 0 1 0 .707l-.036.036a.5.5 0 0 1-.707 0L2.428 2.965a.5.5 0 0 1 0-.707l.037-.036a.5.5 0 0 1 .707 0l1.414 1.414zm-1.09 2.823h-2a.5.5 0 0 1-.5-.5v-.051a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v.05a.5.5 0 0 1-.5.5z"/></symbol><symbol viewBox="0 0 16 16" id="user" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0 8c-6.888 0-6.976-.78-6.976-2.52S2.144 8 8 8s6.976 2.692 6.976 4.48c0 1.788-.088 2.52-6.976 2.52z"/></symbol><symbol viewBox="0 0 16 16" id="users" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10.521 8.01C15.103 8.19 16 10.755 16 12.48c0 1.533-.056 2.29-3.808 2.475.609-.54.808-1.331.808-2.475 0-1.911-.804-3.503-2.479-4.47zm-1.67-1.228A3.987 3.987 0 0 0 9.976 4a3.987 3.987 0 0 0-1.125-2.782 3 3 0 1 1 0 5.563zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6zM6 15c-5.924 0-6-.78-6-2.52S.964 8 6 8s6 2.692 6 4.48c0 1.788-.076 2.52-6 2.52z"/></symbol><symbol viewBox="0 0 16 16" id="volume-up" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M1 5h1v6H1a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1zm2 0l4.445-2.964A1 1 0 0 1 9 2.87v10.26a1 1 0 0 1-1.555.833L3 11V5zm10.283 7.89a.5.5 0 0 1-.66-.752A5.485 5.485 0 0 0 14.5 8c0-1.601-.687-3.09-1.865-4.128a.5.5 0 0 1 .661-.75A6.484 6.484 0 0 1 15.5 8a6.485 6.485 0 0 1-2.217 4.89zm-2.002-2.236a.5.5 0 1 1-.652-.758c.55-.472.871-1.157.871-1.896 0-.732-.315-1.411-.856-1.883a.5.5 0 0 1 .658-.753A3.492 3.492 0 0 1 12.5 8c0 1.033-.45 1.994-1.219 2.654z"/></symbol><symbol viewBox="0 0 16 16" id="warning" xmlns="http://www.w3.org/2000/svg"><path d="M15.34 10.479A3 3 0 0 1 12.756 15h-9.51A3 3 0 0 1 .66 10.479l4.755-8.083a3 3 0 0 1 5.172 0l4.755 8.083zm-6.478-7.07a1 1 0 0 0-1.724 0l-4.755 8.084A1 1 0 0 0 3.245 13h9.51a1 1 0 0 0 .862-1.507L8.862 3.41zM8 5a1 1 0 0 1 1 1v2a1 1 0 1 1-2 0V6a1 1 0 0 1 1-1zm0 7a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="work" xmlns="http://www.w3.org/2000/svg"><path d="M12 3h1a3 3 0 0 1 3 3v7a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V6a3 3 0 0 1 3-3h1V2a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v1zM6 2v1h4V2H6zM3 5a1 1 0 0 0-1 1v7a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1H3zm1.5 1a.5.5 0 0 1 .5.5v6a.5.5 0 1 1-1 0v-6a.5.5 0 0 1 .5-.5zm7 0a.5.5 0 0 1 .5.5v6a.5.5 0 1 1-1 0v-6a.5.5 0 0 1 .5-.5z"/></symbol></svg>
\ No newline at end of file +<?xml version="1.0" encoding="utf-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><symbol viewBox="0 0 16 16" id="abuse" xmlns="http://www.w3.org/2000/svg"><path d="M11.408.328l4.029 3.222A1.5 1.5 0 0 1 16 4.72v6.555a1.5 1.5 0 0 1-.563 1.171l-4.026 3.224a1.5 1.5 0 0 1-.937.329H5.529a1.5 1.5 0 0 1-.937-.328L.563 12.45A1.5 1.5 0 0 1 0 11.28V4.724a1.5 1.5 0 0 1 .563-1.171L4.589.329A1.5 1.5 0 0 1 5.526 0h4.945c.34 0 .67.116.937.328zM10.296 2H5.702L2 4.964v6.074L5.704 14h4.594L14 11.036V4.962L10.296 2zM8 4a1 1 0 0 1 1 1v3a1 1 0 1 1-2 0V5a1 1 0 0 1 1-1zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="account" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M9.195 9.965l-.568-.875a.25.25 0 0 1 .015-.294l.405-.5a.25.25 0 0 1 .283-.075l.938.36c.257-.183.543-.325.851-.42l.322-.988A.25.25 0 0 1 11.679 7h.642a.25.25 0 0 1 .238.173l.322.988c.308.095.594.237.851.42l.938-.36a.25.25 0 0 1 .283.076l.405.5a.25.25 0 0 1 .015.293l-.568.875c.113.297.18.616.193.95l.898.54a.25.25 0 0 1 .115.27l-.144.626a.25.25 0 0 1-.222.193l-1.115.098a3.015 3.015 0 0 1-.512.608l.165 1.18a.25.25 0 0 1-.138.259l-.577.281a.25.25 0 0 1-.29-.05l-.874-.905a3.035 3.035 0 0 1-.608 0l-.875.904a.25.25 0 0 1-.289.051l-.577-.281a.25.25 0 0 1-.138-.26l.165-1.18a3.015 3.015 0 0 1-.512-.607l-1.115-.098a.25.25 0 0 1-.222-.193l-.144-.626a.25.25 0 0 1 .115-.27l.898-.54c.013-.334.08-.653.193-.95zM6.789 8.023A12.845 12.845 0 0 0 6 8c-5.036 0-6 2.74-6 4.48C0 14.22.076 15 6 15c.553 0 1.055-.006 1.51-.02A5.977 5.977 0 0 1 6 11c0-1.083.287-2.1.79-2.977zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6zM12 12a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="admin" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M13.162 2.5a3.5 3.5 0 0 1-3.163 5.479L6.08 14.766a1.5 1.5 0 0 1-2.598-1.5L7.4 6.479A3.5 3.5 0 0 1 10.564 1L8.9 3.88l2.599 1.5 1.663-2.88zm-8.63 11.949a.5.5 0 1 0 .5-.866.5.5 0 0 0-.5.866z"/></symbol><symbol viewBox="0 0 16 16" id="angle-double-left" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10.414 7.95l4.243-4.243a1 1 0 0 0-1.414-1.414l-4.95 4.95a.997.997 0 0 0 0 1.414l4.95 4.95a1 1 0 1 0 1.414-1.415L10.414 7.95zm-7 0l4.243-4.243a1 1 0 0 0-1.414-1.414l-4.95 4.95a.997.997 0 0 0 0 1.414l4.95 4.95a1 1 0 0 0 1.414-1.415L3.414 7.95z"/></symbol><symbol viewBox="0 0 16 16" id="angle-double-right" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M5.535 7.95L1.292 3.707a1 1 0 0 1-.281-.695 1 1 0 1 1 1.695-.719l4.95 4.95a.998.998 0 0 1 0 1.414l-4.95 4.95a1.002 1.002 0 0 1-.707.293c-.549 0-1-.452-1-1 0-.266.106-.52.293-.708L5.535 7.95zm7 0L8.292 3.707a1 1 0 0 1-.281-.695 1 1 0 1 1 1.695-.719l4.95 4.95a.998.998 0 0 1 0 1.414l-4.95 4.95a1.002 1.002 0 0 1-.707.293c-.549 0-1-.452-1-1.001 0-.265.106-.519.293-.707l4.243-4.242z"/></symbol><symbol viewBox="0 0 16 16" id="angle-down" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8 10.243l-4.95-4.95a1 1 0 0 0-1.414 1.414l5.657 5.657a.997.997 0 0 0 1.414 0l5.657-5.657a1 1 0 0 0-1.414-1.414L8 10.243z"/></symbol><symbol viewBox="0 0 16 16" id="angle-left" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M5.757 8l4.95-4.95a1 1 0 1 0-1.414-1.414L3.636 7.293a.997.997 0 0 0 0 1.414l5.657 5.657a1 1 0 0 0 1.414-1.414L5.757 8z"/></symbol><symbol viewBox="0 0 16 16" id="angle-right" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10.243 8l-4.95-4.95a1 1 0 0 1 1.414-1.414l5.657 5.657a.997.997 0 0 1 0 1.414l-5.657 5.657a1 1 0 0 1-1.414-1.414L10.243 8z"/></symbol><symbol viewBox="0 0 16 16" id="angle-up" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8 6.757l-4.95 4.95a1 1 0 1 1-1.414-1.414l5.657-5.657a.997.997 0 0 1 1.414 0l5.657 5.657a1 1 0 0 1-1.414 1.414L8 6.757z"/></symbol><symbol viewBox="0 0 16 16" id="appearance" xmlns="http://www.w3.org/2000/svg"><path d="M11.161 12.456l.232.121c.1.053.175.094.249.137.53.318.844.75.857 1.402.012 1.397-1.116 1.756-3.12 1.858a23.85 23.85 0 0 1-1.38.026A8 8 0 0 1 0 8a8 8 0 0 1 8-8c4.417 0 7.998 3.582 7.998 7.977.06 2.621-1.312 3.586-4.48 3.648-.602.008-1.068.043-1.4.104.228.192.598.47 1.043.727zm-3.287-.943c-.019-1.495 1.228-1.856 3.611-1.888C13.67 9.582 14.028 9.33 13.998 8A6 6 0 1 0 8 14c.603 0 .91-.004 1.277-.023a9.7 9.7 0 0 0 .478-.035c-1.172-.738-1.868-1.47-1.88-2.43zM6 5a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm6 3a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm-2-3a1 1 0 1 1 0-2 1 1 0 0 1 0 2zM4 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="applications" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M1 0h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1V1a1 1 0 0 1 1-1zm0 6h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1zm6-6h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V1a1 1 0 0 1 1-1zm0 1v2h2V1H7zm0 5h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1zm6-6h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1V1a1 1 0 0 1 1-1zm0 6h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1zm0 1v2h2V7h-2zM1 12h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1zm0 1v2h2v-2H1zm6-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1zm6 0h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1z"/></symbol><symbol viewBox="0 0 16 16" id="approval" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10.536 10.657l2.828-2.829a1 1 0 0 1 1.414 1.415l-3.535 3.535a.997.997 0 0 1-1.415 0l-2.12-2.121A1 1 0 1 1 9.12 9.243l1.415 1.414zM7.632 8.109A2 2 0 0 0 7 11.364l2.121 2.121a1.996 1.996 0 0 0 2.807.021C11.686 14.554 10.627 15 6 15c-5.924 0-6-.78-6-2.52S.964 8 6 8c.6 0 1.142.038 1.632.109zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6z"/></symbol><symbol viewBox="0 0 16 16" id="arrow-right" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M9 6H2a2 2 0 1 0 0 4h7v2.586a1 1 0 0 0 1.707.707l4.586-4.586a1 1 0 0 0 0-1.414l-4.586-4.586A1 1 0 0 0 9 3.414V6z"/></symbol><symbol viewBox="0 0 16 16" id="assignee" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M12 5V4a1 1 0 0 1 2 0v1h1a1 1 0 0 1 0 2h-1v1a1 1 0 0 1-2 0V7h-1a1 1 0 0 1 0-2h1zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6zM6 15c-5.924 0-6-.78-6-2.52S.964 8 6 8s6 2.692 6 4.48c0 1.788-.076 2.52-6 2.52z"/></symbol><symbol viewBox="0 0 16 16" id="bold" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M2 15V1a1 1 0 0 1 1-1h4.604c.93 0 1.762.088 2.495.264.733.176 1.353.445 1.863.807.509.363.897.82 1.164 1.369.268.549.401 1.197.401 1.945 0 .366-.045.718-.137 1.055-.091.337-.23.652-.417.945a3.453 3.453 0 0 1-.71.796 3.645 3.645 0 0 1-1.021.588c.469.117.87.295 1.203.533.333.238.608.515.824.83.216.315.374.657.473 1.027.099.37.148.75.148 1.138 0 1.553-.5 2.725-1.5 3.516-1 .791-2.423 1.187-4.27 1.187H3a1 1 0 0 1-1-1zm3.297-5.967v4.319H8.12c.425 0 .791-.053 1.099-.16.307-.106.564-.252.769-.44.205-.186.357-.406.456-.659.099-.252.148-.529.148-.83a3.04 3.04 0 0 0-.131-.928 1.78 1.78 0 0 0-.413-.703 1.8 1.8 0 0 0-.73-.445c-.3-.103-.66-.154-1.077-.154H5.297zm0-2.33h2.44c.842-.014 1.468-.192 1.878-.533.41-.34.616-.826.616-1.456 0-.725-.21-1.247-.632-1.566-.421-.318-1.086-.478-1.995-.478H5.297v4.033z"/></symbol><symbol viewBox="0 0 16 16" id="book" xmlns="http://www.w3.org/2000/svg"><path d="M7 2H5a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2v4.191a.5.5 0 0 1-.724.447l-1.052-.526a.5.5 0 0 0-.448 0l-1.052.526A.5.5 0 0 1 7 6.191V2zM5 0h6a4 4 0 0 1 4 4v8a4 4 0 0 1-4 4H5a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4z"/></symbol><symbol viewBox="0 0 16 16" id="branch" xmlns="http://www.w3.org/2000/svg"><path d="M6 11.978v.29a2 2 0 1 1-2 0V3.732a2 2 0 1 1 2 0v3.849c.592-.491 1.31-.854 2.15-1.081 1.308-.353 1.875-.882 1.893-1.743a2 2 0 1 1 2.002-.051C12.053 6.54 10.857 7.84 8.67 8.43 7.056 8.867 6.195 9.98 6 11.978zM5 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm6 1a1 1 0 1 0 0-2 1 1 0 0 0 0 2zM5 15a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="calendar" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M12 2h2a2 2 0 0 1 2 2H0a2 2 0 0 1 2-2h2V1a1 1 0 1 1 2 0v1h4V1a1 1 0 1 1 2 0v1zM0 4h16v9a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V4zm2 2.5V13a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V6.5a.5.5 0 0 0-.5-.5h-11a.5.5 0 0 0-.5.5zM5 8h2a1 1 0 1 1 0 2H5a1 1 0 1 1 0-2z"/></symbol><symbol viewBox="0 0 16 16" id="cancel" xmlns="http://www.w3.org/2000/svg"><path d="M3.11 4.523a6 6 0 0 0 8.367 8.367L3.109 4.524zM4.522 3.11l8.368 8.368A6 6 0 0 0 4.524 3.11zM8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16z"/></symbol><symbol viewBox="0 0 16 16" id="chevron-down" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8.078 8.2l3.535-3.536a2 2 0 0 1 2.828 2.828l-4.949 4.95c-.39.39-.902.586-1.414.586a1.994 1.994 0 0 1-1.414-.586l-4.95-4.95a2 2 0 1 1 2.828-2.828l3.536 3.535z"/></symbol><symbol viewBox="0 0 16 16" id="chevron-left" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7.977 7.998l3.535-3.535a2 2 0 1 0-2.828-2.828l-4.95 4.949c-.39.39-.586.902-.586 1.414 0 .512.196 1.024.586 1.414l4.95 4.95a2 2 0 1 0 2.828-2.828L7.977 7.998z"/></symbol><symbol viewBox="0 0 16 16" id="chevron-right" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8.22 7.998L4.683 4.463a2 2 0 0 1 2.828-2.828l4.95 4.949c.39.39.586.902.586 1.414a1.99 1.99 0 0 1-.586 1.414l-4.95 4.95a2 2 0 0 1-2.828-2.828l3.535-3.536z"/></symbol><symbol viewBox="0 0 16 16" id="chevron-up" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7.778 8.957l3.535 3.535a2 2 0 1 0 2.828-2.828l-4.949-4.95a1.994 1.994 0 0 0-1.414-.586c-.512 0-1.024.196-1.414.586l-4.95 4.95a2 2 0 1 0 2.828 2.828l3.536-3.535z"/></symbol><symbol viewBox="0 0 16 16" id="clock" xmlns="http://www.w3.org/2000/svg"><path d="M9 7h1a1 1 0 0 1 0 2H8a.997.997 0 0 1-1-1V5a1 1 0 1 1 2 0v2zm-1 9A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12z"/></symbol><symbol viewBox="0 0 16 16" id="close" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M9.414 8l4.95-4.95a1 1 0 0 0-1.414-1.414L8 6.586l-4.95-4.95A1 1 0 0 0 1.636 3.05L6.586 8l-4.95 4.95a1 1 0 1 0 1.414 1.414L8 9.414l4.95 4.95a1 1 0 1 0 1.414-1.414L9.414 8z"/></symbol><symbol viewBox="0 0 16 16" id="code" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M15.871 8.243a.997.997 0 0 0-.293-.707L12.75 4.707a1 1 0 0 0-1.414 1.414l2.12 2.122-2.12 2.121a1 1 0 0 0 1.414 1.414l2.828-2.828a.997.997 0 0 0 .293-.707zm-13.243 0L4.75 6.12a1 1 0 1 0-1.414-1.414L.507 7.536a.997.997 0 0 0 0 1.414l2.829 2.828a1 1 0 1 0 1.414-1.414L2.628 8.243zm6.407-4.107a1 1 0 0 1 .707 1.225L8.19 11.157a1 1 0 1 1-1.931-.518L7.81 4.843a1 1 0 0 1 1.224-.707z"/></symbol><symbol viewBox="0 0 16 16" id="comment" xmlns="http://www.w3.org/2000/svg"><path d="M1.707 15.707C1.077 16.337 0 15.891 0 15V3a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H5.414l-3.707 3.707zM2 12.586l2.293-2.293A1 1 0 0 1 5 10h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v9.586z"/></symbol><symbol viewBox="0 0 16 16" id="comment-dots" xmlns="http://www.w3.org/2000/svg"><path d="M1.707 15.707C1.077 16.337 0 15.891 0 15V3a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H5.414l-3.707 3.707zM2 12.586l2.293-2.293A1 1 0 0 1 5 10h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v9.586zM5 7a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="comment-next" xmlns="http://www.w3.org/2000/svg"><path d="M8 5V4a.5.5 0 0 1 .8-.4l2.667 2a.5.5 0 0 1 0 .8L8.8 8.4A.5.5 0 0 1 8 8V7H6a1 1 0 1 1 0-2h2zM1.707 15.707C1.077 16.337 0 15.891 0 15V3a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H5.414l-3.707 3.707zM2 12.586l2.293-2.293A1 1 0 0 1 5 10h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v9.586z"/></symbol><symbol viewBox="0 0 16 16" id="comments" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M3.75 10L0 13V3a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2H3.75zM13 5h1a2 2 0 0 1 2 2v8l-2.667-2H8a2 2 0 0 1-2-2h4a3 3 0 0 0 3-3V5z"/></symbol><symbol viewBox="0 0 16 16" id="commit" xmlns="http://www.w3.org/2000/svg"><path d="M8 10a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm3.876-1.008a4.002 4.002 0 0 1-7.752 0A1.01 1.01 0 0 1 4 9H1a1 1 0 1 1 0-2h3c.042 0 .083.003.124.008a4.002 4.002 0 0 1 7.752 0A1.01 1.01 0 0 1 12 7h3a1 1 0 0 1 0 2h-3a1.01 1.01 0 0 1-.124-.008z"/></symbol><symbol viewBox="0 0 16 16" id="credit-card" xmlns="http://www.w3.org/2000/svg"><path d="M14 5a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1h12zm0 3H2v3a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V8zM3 2h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3zm6.5 8h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1z"/></symbol><symbol viewBox="0 0 16 16" id="disk" xmlns="http://www.w3.org/2000/svg"><path d="M16 11.764V3a3 3 0 0 0-3-3H3a3 3 0 0 0-3 3v8.764A2.989 2.989 0 0 1 2 11V3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v8c.768 0 1.47.289 2 .764zM2 12h12a2 2 0 1 1 0 4H2a2 2 0 1 1 0-4zm10 1a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"/></symbol><symbol viewBox="0 0 16 16" id="doc_code" xmlns="http://www.w3.org/2000/svg"><path d="M8 2H5a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V7h-3a2 2 0 0 1-2-2V2zm2 .414V5h2.586L10 2.414zm1.036 7.607a.498.498 0 0 1-.147.354l-1.414 1.414a.5.5 0 0 1-.707-.707l1.06-1.06-1.06-1.061a.5.5 0 0 1 .707-.707l1.414 1.414a.498.498 0 0 1 .147.353zm-4.822 0l1.06 1.061a.5.5 0 0 1-.706.707l-1.414-1.414a.498.498 0 0 1 0-.707l1.414-1.414a.5.5 0 1 1 .707.707l-1.06 1.06zM5 0h4.586A2 2 0 0 1 11 .586L14.414 4A2 2 0 0 1 15 5.414V12a4 4 0 0 1-4 4H5a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4z"/></symbol><symbol viewBox="0 0 16 16" id="doc_image" xmlns="http://www.w3.org/2000/svg"><path d="M8 2H5a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V7h-3a2 2 0 0 1-2-2V2zm2 .414V5h2.586L10 2.414zM7.333 9.667l1.313-1.313a.5.5 0 0 1 .708 0L12 11H4l2.188-1.75a.5.5 0 0 1 .624 0l.521.417zM5 0h4.586A2 2 0 0 1 11 .586L14.414 4A2 2 0 0 1 15 5.414V12a4 4 0 0 1-4 4H5a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4zm.5 8a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zM4 11h8v.7a.3.3 0 0 1-.3.3H4.3a.3.3 0 0 1-.3-.3V11z"/></symbol><symbol viewBox="0 0 16 16" id="doc_text" xmlns="http://www.w3.org/2000/svg"><path d="M8 2H5a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V7h-3a2 2 0 0 1-2-2V2zm2 .414V5h2.586L10 2.414zM5 0h4.586A2 2 0 0 1 11 .586L14.414 4A2 2 0 0 1 15 5.414V12a4 4 0 0 1-4 4H5a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4zm.5 11h5a.5.5 0 1 1 0 1h-5a.5.5 0 1 1 0-1zm0-2h5a.5.5 0 1 1 0 1h-5a.5.5 0 0 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1z"/></symbol><symbol viewBox="0 0 16 16" id="download" xmlns="http://www.w3.org/2000/svg"><path d="M9 12h1a.5.5 0 0 1 .4.8l-2 2.667a.5.5 0 0 1-.8 0l-2-2.667A.5.5 0 0 1 6 12h1V8a1 1 0 1 1 2 0v4zM4 9a1 1 0 1 1 0 2 4 4 0 0 1-1.971-7.481 4 4 0 0 1 6.633-2.505 3.999 3.999 0 0 1 3.82 2.014A4 4 0 0 1 12 11a1 1 0 0 1 0-2 2 2 0 1 0 0-4h-1a2 2 0 0 0-3.112-1.662A2 2 0 1 0 4.268 5H4a2 2 0 1 0 0 4z"/></symbol><symbol viewBox="0 0 16 16" id="duplicate" xmlns="http://www.w3.org/2000/svg"><path d="M14 10h-3a1 1 0 0 1-1-1V6H8.527A.527.527 0 0 0 8 6.527V13a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1v-3zm-4-7H8.527c-.18 0-.355.013-.527.04V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2v2H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h4a3 3 0 0 1 3 3zM8.527 4h2.323a.5.5 0 0 1 .35.143l4.65 4.551a.5.5 0 0 1 .15.357V13a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V6.527A2.527 2.527 0 0 1 8.527 4z"/></symbol><symbol viewBox="0 0 16 16" id="earth" xmlns="http://www.w3.org/2000/svg"><path d="M8.7 2.04l-.082.177c.283.223.422.413.417.571-.008.237-.311.057-.444.274-.133.218.038.542-.112.637-.15.096-.398-.386-.479-.46-.054-.049-.166-.257-.336-.625l-.216-.225a.844.844 0 0 0-.418-.035c-.177.038-.075.1-.035.132.04.032.32.037.452.2.132.164.03.224-.05.298-.054.05-.157.062-.31.035H5.952l-.402.398.03.325.229.455.324-.463c.008-.206.058-.342.15-.41.14-.1.342-.15.534-.085.191.066-.057.218.011.271.068.053.204-.098.313-.02.11.08.07.155.104.322.036.167.254.114.398.328.144.215.19.29.147.483-.043.195-.168.26-.305.232-.138-.028-.107-.246-.275-.348-.168-.102-.266-.114-.386-.054-.12.06-.016.129.023.235.04.106.274.321.224.43-.05.107-.108.116-.42 0-.21-.077-.414-.007-.615.212l-.76.722c-.153.715-.3 1.13-.44 1.243-.211.17-.177-.483-.483-.656-.306-.174-.494-.047-.8-.07-.307-.023-.42.65-.38.873a.434.434 0 0 0 .221.321c.236-.141.39-.184.465-.128.11.084-.144.267-.074.425.07.158.314.069.386.283.073.213.084.48-.05.706-.135.227-.275.178-.4.053-.127-.126-.033-.375-.255-.704-.223-.329-.381-.337-.63-.787-.158-.287-.35-.743-.575-1.366a6 6 0 0 0 3.21 7.198l.001-.075c0-.577-.004-.944-.012-1.102-.011-.236-.95-.945-1.104-1.2-.154-.256-.34-.595-.355-.746-.016-.151.185-.232.344-.325.16-.093-.11-.367.028-.626.137-.258.395-.438.496-.356.101.081.058.228.267.333.209.104.077-.213.456-.178.38.035.143.201.252.216.11.016.113-.127.299-.143.186-.015.282.445.471.622.19.178.452.008.611.043.159.034.267.09.402.255.136.166-.03.352.073.557.103.205 1.07.22 1.433.255.364.034.371.011.371.324s-.166.314-.453.507c-.286.193-.166.462-.38.762-.212.3-.316.062-.622.14-.306.077-.413.382-.452.568-.039.186-.386.094-.877.232-.29.082-.429.144-.569.204a6.002 6.002 0 0 0 7.682-4.3c-.094-.384-.18-.63-.258-.74-.213-.297-.36.21-.924.49-.564.278-.57-.288-.81-.49-.16-.133-.212-.44-.158-.92-.005-.478.02-.828.077-1.049.057-.221.126-.543.207-.965.351-.373.606-.572.764-.595.237-.034.336.374.658.3a.315.315 0 0 0 .035-.01 5.993 5.993 0 0 0-.475-.824l-.309-.043a.646.646 0 0 0-.332-.117c-.205-.02-.025.128-.089.24-.064.112-.235.724-.437.685-.201-.039-.204-.374-.17-.668.036-.294-.077-.35-.2-.412-.124-.062-.325-.213-.556-.295-.232-.082-.123-.175-.093-.274.03-.1.208-.015.193-.058-.014-.044-.313-.135-.266-.167.03-.02.2-.02.506.003l.216-.012.293-.163a.58.58 0 0 0-.376-.22c-.233-.036-.513-.034-.73-.142-.205-.103-.458-.36-.643-.638A5.965 5.965 0 0 0 8.7 2.04zM8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16z"/></symbol><symbol viewBox="0 0 16 16" id="eye" xmlns="http://www.w3.org/2000/svg"><path d="M8 14C4.816 14 2.253 12.284.393 8.981a2 2 0 0 1 0-1.962C2.253 3.716 4.816 2 8 2s5.747 1.716 7.607 5.019a2 2 0 0 1 0 1.962C13.747 12.284 11.184 14 8 14zm0-2c2.41 0 4.338-1.29 5.864-4C12.338 5.29 10.411 4 8 4 5.59 4 3.662 5.29 2.136 8 3.662 10.71 5.589 12 8 12zm0-1a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm1-3a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="eye-slash" xmlns="http://www.w3.org/2000/svg"><path d="M13.618 2.62L1.62 14.619a1 1 0 0 1-.985-1.668l1.525-1.526C1.516 10.742.926 9.927.393 8.981a2 2 0 0 1 0-1.962C2.253 3.716 4.816 2 8 2c1.074 0 2.076.195 3.006.58l.944-.944a1 1 0 0 1 1.668.985zM8.068 11a3 3 0 0 0 2.931-2.932l-2.931 2.931zm-3.02-2.462a3 3 0 0 1 3.49-3.49l.884-.884A6.044 6.044 0 0 0 8 4C5.59 4 3.662 5.29 2.136 8c.445.79.924 1.46 1.439 2.011l1.473-1.473zm.421 5.06l1.658-1.658c.283.04.575.06.873.06 2.41 0 4.338-1.29 5.864-4a11.023 11.023 0 0 0-1.133-1.664l1.418-1.418a12.799 12.799 0 0 1 1.458 2.1 2 2 0 0 1 0 1.963C13.747 12.284 11.184 14 8 14a7.883 7.883 0 0 1-2.53-.402z"/></symbol><symbol viewBox="0 0 16 16" id="file-additions" xmlns="http://www.w3.org/2000/svg"><path d="M7 7V5a1 1 0 1 1 2 0v2h2a1 1 0 0 1 0 2H9v2a1 1 0 0 1-2 0V9H5a1 1 0 1 1 0-2h2zM3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2H3z"/></symbol><symbol viewBox="0 0 16 16" id="file-deletion" xmlns="http://www.w3.org/2000/svg"><path d="M3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2H3zm2 6h6a1 1 0 0 1 0 2H5a1 1 0 1 1 0-2z"/></symbol><symbol viewBox="0 0 16 16" id="file-modified" xmlns="http://www.w3.org/2000/svg"><path d="M3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2H3zm5 4a3 3 0 1 1 0 6 3 3 0 0 1 0-6z"/></symbol><symbol viewBox="0 0 16 16" id="filter" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 6v9l-3.724-1.862A.5.5 0 0 1 6 12.691V6L1.854 1.854A.5.5 0 0 1 2.207 1h11.586a.5.5 0 0 1 .353.854L10 6z"/></symbol><symbol viewBox="0 0 16 16" id="folder" xmlns="http://www.w3.org/2000/svg"><path d="M7.228 5l-.475-1.335A1 1 0 0 0 5.81 3H2v9a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1H7.228zM13 3a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a2 2 0 0 1 2-2h3.81a3 3 0 0 1 2.827 1.995L13 3z"/></symbol><symbol viewBox="0 0 16 16" id="fork" xmlns="http://www.w3.org/2000/svg"><path d="M9 12.268a2 2 0 1 1-2 0V8.874A4.002 4.002 0 0 1 4 5V3.732a2 2 0 1 1 2 0V5a2 2 0 1 0 4 0V3.732a2 2 0 1 1 2 0V5a4.002 4.002 0 0 1-3 3.874v3.394zM11 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zM5 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 12a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="geo-nodes" xmlns="http://www.w3.org/2000/svg"><path d="M9.7 13.1l-.2.2c-.7.8-2 .9-2.8.1-.1 0-.1-.1-.1-.1l-.2-.2c-2 .2-3.4.7-3.4 1.4 0 .8 2.2 1.5 5 1.5s5-.7 5-1.5c0-.7-1.4-1.2-3.3-1.4M7.3 12.7c.4.4 1 .3 1.4-.1C11.6 9.5 13 7 13 5.3 13 2.4 10.8 0 8 0S3 2.4 3 5.3C3 7 4.4 9.5 7.3 12.7M8 2c1.6 0 3 1.4 3 3.3 0 1-1 2.8-3 5.2-2-2.4-3-4.2-3-5.2C5 3.4 6.4 2 8 2"/><circle cx="8" cy="5" r="1"/></symbol><symbol viewBox="0 0 16 16" id="git-merge" xmlns="http://www.w3.org/2000/svg"><path d="M11 12.268V5a1 1 0 0 0-1-1v1a.5.5 0 0 1-.8.4l-2.667-2a.5.5 0 0 1 0-.8L9.2.6a.5.5 0 0 1 .8.4v1a3 3 0 0 1 3 3v7.268a2 2 0 1 1-2 0zm-6 0a2 2 0 1 1-2 0V4.732a2 2 0 1 1 2 0v7.536zM4 4a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm0 11a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm8 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="group" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M3.048 11.997C-.377 11.975.013 11.782.013 10.56.013 9.235.653 8 4 8c.444 0 .84.022 1.194.062.164.435.426.82.76 1.132-1.786.389-2.721 1.353-2.906 2.803zm2.94-7.222a2.993 2.993 0 0 0-.976 1.95 2 2 0 1 1 .975-1.95zm6.964 7.222c-.185-1.45-1.12-2.414-2.906-2.803.334-.311.596-.697.76-1.132C11.16 8.022 11.556 8 12 8c3.346 0 3.987 1.235 3.987 2.56 0 1.222.39 1.415-3.035 1.437zm-1.964-5.272a2.993 2.993 0 0 0-.976-1.95 2 2 0 1 1 .976 1.95zM8 9a2 2 0 1 1 0-4 2 2 0 0 1 0 4zm0 5c-2.177 0-3.987-.115-3.987-1.44S4.653 10 8 10c3.346 0 3.987 1.235 3.987 2.56S10.177 14 8 14z"/></symbol><symbol viewBox="0 0 16 16" id="history" xmlns="http://www.w3.org/2000/svg"><path d="M2.868 3.24a7 7 0 1 1-.043 9.475 1 1 0 0 1 1.478-1.348 5 5 0 1 0 .124-6.865l.796.645a.5.5 0 0 1-.193.873l-3.232.814a.5.5 0 0 1-.622-.504L1.3 3a.5.5 0 0 1 .814-.37l.754.61zM9 8h1a1 1 0 0 1 0 2H8a.997.997 0 0 1-1-1V6a1 1 0 1 1 2 0v2z"/></symbol><symbol viewBox="0 0 16 16" id="home" xmlns="http://www.w3.org/2000/svg"><path d="M8.462 2.177a.505.505 0 0 1-.038.044l.038-.044zm-.787 0l.038.043a.5.5 0 0 1-.038-.043zM3.706 7h8.725L8.069 2.585 3.706 7zM7 13.369V12a1 1 0 0 1 2 0v1.369h3V9H4v4.369h3zM14 9v4.836c0 .833-.657 1.533-1.5 1.533h-9c-.843 0-1.5-.7-1.5-1.533V9h-.448a1.1 1.1 0 0 1-.783-1.873L6.934.887a1.5 1.5 0 0 1 2.269 0l6.165 6.24A1.1 1.1 0 0 1 14.585 9H14z"/></symbol><symbol viewBox="0 0 16 16" id="hook" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 3a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1h4zm0 1H6v1a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1V4zM7 8a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h2a3 3 0 0 1 3 3v2a3 3 0 0 1-3 3v4a2 2 0 1 0 4 0h-.44a.3.3 0 0 1-.25-.466l1.44-2.16a.3.3 0 0 1 .5 0l1.44 2.16a.3.3 0 0 1-.25.466H15a4 4 0 0 1-7 2.646A4 4 0 0 1 1 12H.56a.3.3 0 0 1-.25-.466l1.44-2.16a.3.3 0 0 1 .5 0l1.44 2.16a.3.3 0 0 1-.25.466H3a2 2 0 1 0 4 0V8z"/></symbol><symbol viewBox="0 0 16 16" id="issue-block" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M5.803 8a5.97 5.97 0 0 0-.462 1H4.5a.5.5 0 0 1 0-1h1.303zM4.5 5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1 0-1zm7.5.083a6.04 6.04 0 0 0-2 0V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h2.083a5.96 5.96 0 0 0 .72 2H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h6a3 3 0 0 1 3 3v2.083zm1.121 3.796zM11 16a5 5 0 1 1 0-10 5 5 0 0 1 0 10zm-1.293-2.292a3 3 0 0 0 4.001-4.001l-4.001 4zm-1.415-1.415l4.001-4a3 3 0 0 0-4.001 4.001z"/></symbol><symbol viewBox="0 0 16 16" id="issue-child" xmlns="http://www.w3.org/2000/svg"><path d="M11 8H5v1h1a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1h2V7a.997.997 0 0 1 1-1h3V4H4.5a.5.5 0 0 1-.5-.5v-2a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.5.5H9v2h3a.997.997 0 0 1 1 1v2h2a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1h-5a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1h1V8zm-9 3v2h3v-2H2zm9 0v2h3v-2h-3z"/></symbol><symbol viewBox="0 0 16 16" id="issue-close" xmlns="http://www.w3.org/2000/svg"><path d="M7.536 8.657l2.828-2.829a1 1 0 0 1 1.414 1.415l-3.535 3.535a.997.997 0 0 1-1.415 0l-2.12-2.121A1 1 0 0 1 6.12 7.243l1.415 1.414zM8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12z"/></symbol><symbol viewBox="0 0 16 16" id="issue-duplicate" xmlns="http://www.w3.org/2000/svg"><path d="M10.874 2H12a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3h-2c-.918 0-1.74-.413-2.29-1.063a3.987 3.987 0 0 0 1.988-.984A1 1 0 0 0 10 14h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1h-1V3c0-.345-.044-.68-.126-1zM4 0h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H4z"/></symbol><symbol viewBox="0 0 16 16" id="issue-new" xmlns="http://www.w3.org/2000/svg"><path d="M10 2V1a1 1 0 0 1 2 0v1h1a1 1 0 0 1 0 2h-1v1a1 1 0 0 1-2 0V4H9a1 1 0 1 1 0-2h1zm0 6a1 1 0 0 1 2 0v5a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3h1a1 1 0 1 1 0 2H5a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1V8z"/></symbol><symbol viewBox="0 0 16 16" id="issue-open" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zm0-2a4 4 0 1 1 0-8 4 4 0 0 1 0 8zm0-2a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"/></symbol><symbol viewBox="0 0 16 16" id="issue-open-m" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12z"/></symbol><symbol viewBox="0 0 16 16" id="issue-parent" xmlns="http://www.w3.org/2000/svg"><path d="M11 11H5v1h1.5a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.5.5h-6a.5.5 0 0 1-.5-.5v-2a.5.5 0 0 1 .5-.5H3v-2a.997.997 0 0 1 1-1h3V7H5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1H9v2h3a.997.997 0 0 1 1 1v2h2.5a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.5.5h-6a.5.5 0 0 1-.5-.5v-2a.5.5 0 0 1 .5-.5H11v-1zM6 3v2h4V3H6z"/></symbol><symbol viewBox="0 0 16 16" id="issues" xmlns="http://www.w3.org/2000/svg"><path d="M10.458 15.012l.311.055a3 3 0 0 0 3.476-2.433l1.389-7.879A3 3 0 0 0 13.2 1.28L11.23.933a3.002 3.002 0 0 0-.824-.031c.364.59.58 1.28.593 2.02l1.854.328a1 1 0 0 1 .811 1.158l-1.389 7.879a1 1 0 0 1-1.158.81l-.118-.02a3.98 3.98 0 0 1-.541 1.935zM3 0h4a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3z"/></symbol><symbol viewBox="0 0 16 16" id="key" xmlns="http://www.w3.org/2000/svg"><path d="M7.575 6.689a4.002 4.002 0 0 1 6.274-4.86 4 4 0 0 1-4.86 6.274l-2.21 2.21.706.708a1 1 0 1 1-1.414 1.414l-.707-.707-.707.707.707.707a1 1 0 1 1-1.414 1.414l-.707-.707a1 1 0 0 1-1.414-1.414l5.746-5.746zm2.032-.618a2 2 0 1 0 2.828-2.828A2 2 0 0 0 9.607 6.07z"/></symbol><symbol viewBox="0 0 16 16" id="key-2" xmlns="http://www.w3.org/2000/svg"><path d="M5.172 14.157l-.344.344-2.485.133a.462.462 0 0 1-.497-.503l.14-2.24a.599.599 0 0 1 .177-.382l5.155-5.155a4 4 0 1 1 2.828 2.828l-1.439 1.44-1.06-.354-.708.707.354 1.06-.707.708-1.06-.354-.708.707.354 1.06zm6.01-8.839a1 1 0 1 0 1.414-1.414 1 1 0 0 0-1.414 1.414z"/></symbol><symbol viewBox="0 0 16 16" id="label" xmlns="http://www.w3.org/2000/svg"><path d="M11.782 14.718a3 3 0 0 1-4.242 0L1.652 8.829a2 2 0 0 1-.565-1.702l.54-3.703a2 2 0 0 1 1.69-1.69l3.703-.54a2 2 0 0 1 1.703.564l5.888 5.888a3 3 0 0 1 0 4.243l-2.829 2.829zm1.415-5.657L7.309 3.173l-3.703.54-.54 3.702 5.888 5.888a1 1 0 0 0 1.414 0l2.829-2.828a1 1 0 0 0 0-1.414zM5.732 5.525A1 1 0 1 1 7.146 6.94a1 1 0 0 1-1.414-1.414z"/></symbol><symbol viewBox="0 0 16 16" id="labels" xmlns="http://www.w3.org/2000/svg"><path d="M9.424 2.254l2.08-.905a1 1 0 0 1 1.206.326l3.013 4.12a1 1 0 0 1 .16.849l-1.947 7.264a3 3 0 0 1-3.675 2.122l-.5-.135a3.999 3.999 0 0 0 1.082-1.782 1 1 0 0 0 1.16-.722l1.823-6.802-2.258-3.087-.687.299a2 2 0 0 0-.628-.88l-.829-.667zM.377 3.7L4.4.498a1 1 0 0 1 1.25.003L9.627 3.7a1 1 0 0 1 .373.78V13a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V4.482A1 1 0 0 1 .377 3.7zM2 13a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1V4.958L5.02 2.561 2 4.964V13zm3-6a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="leave" xmlns="http://www.w3.org/2000/svg"><path d="M11 7V5.883a.5.5 0 0 1 .757-.429l3.528 2.117a.5.5 0 0 1 0 .858l-3.528 2.117a.5.5 0 0 1-.757-.43V9H7a1 1 0 1 1 0-2h4zm-2 6.256a1 1 0 0 1 2 0A2.744 2.744 0 0 1 8.256 16H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h5.19A2.81 2.81 0 0 1 11 2.81a1 1 0 0 1-2 0A.81.81 0 0 0 8.19 2H3a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h5.256c.41 0 .744-.333.744-.744z"/></symbol><symbol viewBox="0 0 16 16" id="level-up" xmlns="http://www.w3.org/2000/svg"><path fill="#2E2E2E" fill-rule="evenodd" d="M7 6h3.489a.5.5 0 0 0 .373-.832L6.374.117a.5.5 0 0 0-.748 0l-4.488 5.05A.5.5 0 0 0 1.51 6H5v7a3 3 0 0 0 3 3h6a1 1 0 0 0 0-2H8a1 1 0 0 1-1-1V6z"/></symbol><symbol viewBox="0 0 16 16" id="license" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M12.56 8.9l2.66 4.606a.3.3 0 0 1-.243.45l-1.678.094a.1.1 0 0 0-.078.044l-.953 1.432a.3.3 0 0 1-.51-.016L9.097 10.9a5.994 5.994 0 0 0 3.464-2zm-5.23 2.063L4.707 15.51a.3.3 0 0 1-.51.016l-.953-1.432a.1.1 0 0 0-.078-.044l-1.678-.094a.3.3 0 0 1-.243-.45l2.48-4.297a5.983 5.983 0 0 0 3.607 1.754zM8 10A5 5 0 1 1 8 0a5 5 0 0 1 0 10zm0-2a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-1a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"/></symbol><symbol viewBox="0 0 16 16" id="link" xmlns="http://www.w3.org/2000/svg"><path d="M6.986 3.35l2.12-2.122a4 4 0 0 1 5.657 5.657l-2.828 2.829a4 4 0 0 1-5.657 0 1 1 0 0 1 1.414-1.415 2 2 0 0 0 2.829 0l2.828-2.828a2 2 0 1 0-2.828-2.828l-1.001 1a5.018 5.018 0 0 0-2.534-.294zm2.12 9.192l-2.12 2.121a4 4 0 1 1-5.658-5.656l2.829-2.829a4 4 0 0 1 5.657 0 1 1 0 1 1-1.415 1.414 2 2 0 0 0-2.828 0l-2.828 2.829a2 2 0 1 0 2.828 2.828l1.001-1.001a5.018 5.018 0 0 0 2.534.294z"/></symbol><symbol viewBox="0 0 16 16" id="list-bulleted" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M1 4a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm0 5a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4-7h10a1 1 0 0 1 0 2H5a1 1 0 1 1 0-2zm0 5h10a1 1 0 0 1 0 2H5a1 1 0 1 1 0-2zm-4 7a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4-2h10a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2z"/></symbol><symbol viewBox="0 0 16 16" id="list-numbered" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M6 2h8a1 1 0 0 1 0 2H6a1 1 0 1 1 0-2zm0 5h8a1 1 0 0 1 0 2H6a1 1 0 1 1 0-2zm0 5h8a1 1 0 0 1 0 2H6a1 1 0 0 1 0-2zM1.156 5v-.828h.816V2.204h-.72v-.636c.432-.084.708-.192.996-.372h.756v2.976h.684V5H1.156zm-.18 5v-.588c.9-.828 1.596-1.464 1.596-1.98 0-.342-.192-.504-.468-.504-.252 0-.444.18-.624.36l-.552-.552c.396-.42.756-.612 1.32-.612.768 0 1.308.492 1.308 1.248 0 .612-.576 1.284-1.092 1.812.192-.024.468-.048.636-.048h.636V10H.976zm1.26 5.072c-.618 0-1.068-.204-1.356-.54l.468-.648c.234.216.51.36.78.36.336 0 .552-.12.552-.36 0-.288-.15-.456-.948-.456v-.72c.636 0 .828-.168.828-.432 0-.228-.138-.348-.396-.348-.252 0-.432.108-.672.312l-.516-.624c.372-.312.768-.492 1.236-.492.84 0 1.38.384 1.38 1.074 0 .366-.204.642-.612.822v.024c.432.132.732.432.732.912 0 .72-.684 1.116-1.476 1.116z"/></symbol><symbol viewBox="0 0 16 16" id="location" xmlns="http://www.w3.org/2000/svg"><path d="M8.755 15.144a1 1 0 0 1-1.51 0C3.748 11.114 2 8.065 2 6a6 6 0 1 1 12 0c0 2.065-1.748 5.113-5.245 9.144zM12 6a4 4 0 1 0-8 0c0 1.314 1.312 3.71 4 6.944C10.688 9.71 12 7.314 12 6zM8 8a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"/></symbol><symbol viewBox="0 0 16 16" id="location-dot" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M6.314 13.087C4.382 13.295 3 13.85 3 14.5c0 .828 2.239 1.5 5 1.5s5-.672 5-1.5c0-.65-1.382-1.205-3.314-1.413l-.202.225a2 2 0 0 1-2.968 0l-.202-.225zm2.428-.445a1 1 0 0 1-1.484 0C4.419 9.5 3 7.037 3 5.252 3 2.353 5.239 0 8 0s5 2.352 5 5.253c0 1.784-1.42 4.247-4.258 7.389zM11 5.252C11 3.436 9.634 2 8 2S5 3.435 5 5.253c0 1.027.974 2.824 3 5.203 2.026-2.38 3-4.176 3-5.203zM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="lock" xmlns="http://www.w3.org/2000/svg"><path d="M10 5V4h2v1a3 3 0 0 1 3 3v5a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V8a3 3 0 0 1 3-3V4h2v1h4zM4 7a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V8a1 1 0 0 0-1-1H4zm0-3a4 4 0 1 1 8 0h-2a2 2 0 1 0-4 0H4z"/></symbol><symbol viewBox="0 0 16 16" id="lock-open" xmlns="http://www.w3.org/2000/svg"><path d="M4.044 4a4 4 0 0 1 6.99-2.658 1 1 0 1 1-1.495 1.33A2 2 0 0 0 6.044 4a.998.998 0 0 1-.07.367v.701H12a3 3 0 0 1 3 3v5a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3v-5a3 3 0 0 1 2.974-3V4h.07zM4 7.07a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-5a1 1 0 0 0-1-1H4z"/></symbol><symbol viewBox="0 0 16 16" id="log" xmlns="http://www.w3.org/2000/svg"><path d="M4 0h8a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H4zm1 4a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm0 3a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3-5h3a1 1 0 0 1 0 2H8a1 1 0 1 1 0-2zm0 3h3a1 1 0 0 1 0 2H8a1 1 0 1 1 0-2zm-3 5a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3-2h3a1 1 0 0 1 0 2H8a1 1 0 0 1 0-2z"/></symbol><symbol viewBox="0 0 16 16" id="mail" xmlns="http://www.w3.org/2000/svg"><path d="M14 5.6L9.338 9.796a2 2 0 0 1-2.676 0L2 5.6V11a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V5.6zM3 2h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3zm.212 2L8 8.31 12.788 4H3.212z"/></symbol><symbol viewBox="0 0 16 16" id="merge-request-close" xmlns="http://www.w3.org/2000/svg"><path d="M9.414 8l1.414 1.414a1 1 0 1 1-1.414 1.414L8 9.414l-1.414 1.414a1 1 0 1 1-1.414-1.414L6.586 8 5.172 6.586a1 1 0 1 1 1.414-1.414L8 6.586l1.414-1.414a1 1 0 1 1 1.414 1.414L9.414 8zM8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12z"/></symbol><symbol viewBox="0 0 16 16" id="messages" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8.588 8.942l1.173 5.862A1 1 0 0 1 8.78 16H7.22a1 1 0 0 1-.98-1.196l1.172-5.862a3.014 3.014 0 0 0 1.176 0zM8 8a2 2 0 1 1 0-4 2 2 0 0 1 0 4zM4.464 2.464L5.88 3.88a3 3 0 0 0 0 4.242L4.464 9.536a5 5 0 0 1 0-7.072zm7.072 7.072L10.12 8.12a3 3 0 0 0 0-4.242l1.415-1.415a5 5 0 0 1 0 7.072zM2.343.343l1.414 1.414a6 6 0 0 0 0 8.486l-1.414 1.414a8 8 0 0 1 0-11.314zm11.314 11.314l-1.414-1.414a6 6 0 0 0 0-8.486L13.657.343a8 8 0 0 1 0 11.314z"/></symbol><symbol viewBox="0 0 16 16" id="mobile-issue-close" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M5.657 10.728L2.12 7.192A1 1 0 1 0 .707 8.607l4.243 4.242a.997.997 0 0 0 1.414 0l8.485-8.485a1 1 0 1 0-1.414-1.414l-7.778 7.778z"/></symbol><symbol viewBox="0 0 16 16" id="monitor" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 13v1h3a1 1 0 0 1 0 2H3a1 1 0 0 1 0-2h3v-1H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v7a3 3 0 0 1-3 3h-3zM3 2a1 1 0 0 0-1 1v7a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3zm5.723 6.416l-2.66-1.773-1.71 1.71a.5.5 0 1 1-.707-.707l2-2a.5.5 0 0 1 .631-.062l2.66 1.773 2.71-2.71a.5.5 0 0 1 .707.707l-3 3a.5.5 0 0 1-.631.062z"/></symbol><symbol viewBox="0 0 16 16" id="more" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8 4a2 2 0 1 1 0-4 2 2 0 0 1 0 4zm0 6a2 2 0 1 1 0-4 2 2 0 0 1 0 4zm0 6a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"/></symbol><symbol viewBox="0 0 16 16" id="notifications" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M6 14H2.435a2 2 0 0 1-1.761-2.947c.962-1.788 1.521-3.065 1.68-3.832.322-1.566.947-5.501 4.65-6.134a1 1 0 1 1 1.994-.024c3.755.528 4.375 4.27 4.761 6.043.188.86.742 2.188 1.661 3.982A2 2 0 0 1 13.64 14H10a2 2 0 1 1-4 0zm5.805-6.468c-.325-1.492-.37-1.674-.61-2.288C10.6 3.716 9.742 3 8.07 3c-1.608 0-2.49.718-3.103 2.197-.28.676-.356.982-.654 2.428-.208 1.012-.827 2.424-1.877 4.375H13.64c-.993-1.937-1.6-3.396-1.835-4.468z"/></symbol><symbol viewBox="0 0 16 16" id="notifications-off" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M13.26 5.089c.243.757.382 1.478.5 2.017.187.86.74 2.188 1.66 3.982A2 2 0 0 1 13.64 14H10a2 2 0 1 1-4 0H4.35l2-2h7.29c-.993-1.937-1.6-3.396-1.835-4.468-.07-.326-.129-.59-.178-.81l1.634-1.633zM10.943 1.75l-1.48 1.48C9.07 3.076 8.612 3 8.069 3c-1.608 0-2.49.718-3.103 2.197-.28.676-.356.982-.654 2.428-.065.317-.17.673-.317 1.073L.45 12.242a1.99 1.99 0 0 1 .224-1.19c.962-1.787 1.521-3.064 1.68-3.831.322-1.566.947-5.501 4.65-6.134a1 1 0 1 1 1.994-.024 4.867 4.867 0 0 1 1.944.688zm2.932-.105a1 1 0 0 1 0 1.415L2.561 14.374a1 1 0 1 1-1.415-1.414L12.46 1.646a1 1 0 0 1 1.414 0z"/></symbol><symbol viewBox="0 0 16 16" id="overview" xmlns="http://www.w3.org/2000/svg"><path d="M2 0h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2zm0 2v3h3V2H2zm9-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2h-3a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2zm0 2v3h3V2h-3zM2 9h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2zm0 2v3h3v-3H2zm9-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2h-3a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2zm0 2v3h3v-3h-3z"/></symbol><symbol viewBox="0 0 16 16" id="pencil" xmlns="http://www.w3.org/2000/svg"><path d="M13.02 1.293l1.414 1.414a1 1 0 0 1 0 1.414L4.119 14.436a1 1 0 0 1-.704.293l-2.407.008L1 12.316a1 1 0 0 1 .293-.71L11.605 1.292a1 1 0 0 1 1.414 0zm-1.416 1.415l-.707.707L12.31 4.83l.707-.707-1.414-1.415zM3.411 13.73l1.123-1.122H3.12v-1.415L2 12.312l.005 1.422 1.406-.005z"/></symbol><symbol viewBox="0 0 16 16" id="pipeline" xmlns="http://www.w3.org/2000/svg"><path d="M8.969 7.25a2 2 0 1 1-1.938 0A1.002 1.002 0 0 1 7 7V5.083a.2.2 0 0 1 .06-.142l.877-.87a.1.1 0 0 1 .141 0l.864.87A.2.2 0 0 1 9 5.083V7c0 .086-.01.17-.031.25zM8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zm4.5-4a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm0-3a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm-2 6a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm0-9a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm-5 9a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm0-9a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm-2 6a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm0-3a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zM8 10a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="play" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M2.765 15.835c-.545.321-1.258.159-1.593-.363A1.075 1.075 0 0 1 1 14.89V1.11C1 .496 1.518 0 2.158 0c.214 0 .424.057.607.165l11.684 6.89c.544.321.714 1.005.38 1.526a1.135 1.135 0 0 1-.38.364l-11.684 6.89z"/></symbol><symbol viewBox="0 0 16 16" id="plus" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7 7V1a1 1 0 1 1 2 0v6h6a1 1 0 0 1 0 2H9v6a1 1 0 0 1-2 0V9H1a1 1 0 1 1 0-2h6z"/></symbol><symbol viewBox="0 0 16 16" id="plus-square" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M9 7V4a1 1 0 1 0-2 0v3H4a1 1 0 1 0 0 2h3v3a1 1 0 0 0 2 0V9h3a1 1 0 0 0 0-2H9zM3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3z"/></symbol><symbol viewBox="0 0 16 16" id="plus-square-o" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7 7V5a1 1 0 1 1 2 0v2h2a1 1 0 0 1 0 2H9v2a1 1 0 0 1-2 0V9H5a1 1 0 1 1 0-2h2zM3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3z"/></symbol><symbol viewBox="0 0 16 16" id="preferences" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M5 12h10a1 1 0 0 1 0 2H5a1 1 0 0 1-2 0v-2a1 1 0 0 1 2 0zm-3 0H1a1 1 0 0 0 0 2h1v-2zm11-5h2a1 1 0 0 1 0 2h-2a1 1 0 0 1-2 0V7a1 1 0 0 1 2 0zm-3 0H1a1 1 0 1 0 0 2h9V7zM6 2h9a1 1 0 0 1 0 2H6a1 1 0 1 1-2 0V2a1 1 0 1 1 2 0zM3 2H1a1 1 0 1 0 0 2h2V2z"/></symbol><symbol viewBox="0 0 16 16" id="profile" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zm-4.274-3.404C4.412 9.709 5.694 9 8 9c2.313 0 3.595.7 4.28 1.586A4.997 4.997 0 0 1 8 13a4.997 4.997 0 0 1-4.274-2.404zM8 8a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"/></symbol><symbol viewBox="0 0 16 16" id="project" xmlns="http://www.w3.org/2000/svg"><path d="M8.462 2.177l-.038.044a.505.505 0 0 0 .038-.044zm-.787 0a.5.5 0 0 0 .038.043l-.038-.043zM3.706 7h8.725L8.069 2.585 3.706 7zM7 13.369V12a1 1 0 0 1 2 0v1.369h3V9H4v4.369h3zM14 9v4.836c0 .833-.657 1.533-1.5 1.533h-9c-.843 0-1.5-.7-1.5-1.533V9h-.448a1.1 1.1 0 0 1-.783-1.873L6.934.887a1.5 1.5 0 0 1 2.269 0l6.165 6.24A1.1 1.1 0 0 1 14.585 9H14z"/></symbol><symbol viewBox="0 0 16 16" id="push-rules" xmlns="http://www.w3.org/2000/svg"><path d="M6.268 9a2 2 0 0 1 3.464 0H11a1 1 0 0 1 0 2H9.732a2 2 0 0 1-3.464 0H5a1 1 0 0 1 0-2h1.268zM7 2H4a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1h-1v3.515a.3.3 0 0 1-.434.268l-1.432-.716a.3.3 0 0 0-.268 0l-1.432.716A.3.3 0 0 1 7 5.515V2zM4 0h8a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm4 11a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="question" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm-1.46-5.602h2.233a3.97 3.97 0 0 1 .051-.558c.029-.17.073-.326.133-.469.06-.143.14-.28.242-.41.102-.13.228-.263.38-.399.26-.24.504-.467.733-.683a5.03 5.03 0 0 0 .598-.668c.17-.23.302-.477.399-.742a2.66 2.66 0 0 0 .144-.907c0-.505-.083-.95-.25-1.335a2.55 2.55 0 0 0-.723-.97 3.2 3.2 0 0 0-1.152-.589 5.441 5.441 0 0 0-1.531-.2c-.516 0-.998.063-1.445.188a3.19 3.19 0 0 0-1.168.59c-.331.268-.594.61-.79 1.027-.195.417-.295.917-.3 1.5h2.64c.006-.224.04-.416.102-.578.062-.161.142-.293.238-.394a.921.921 0 0 1 .332-.227 1.04 1.04 0 0 1 .39-.074c.34 0 .593.095.763.285.169.19.254.488.254.895 0 .328-.106.63-.317.906-.21.276-.499.565-.863.867-.214.182-.39.374-.531.574-.141.2-.253.42-.336.657a3.656 3.656 0 0 0-.176.777 7.89 7.89 0 0 0-.05.937zm-.321 2.375c0 .188.035.362.105.524.07.161.17.3.301.418.13.117.284.21.46.277.178.068.376.102.595.102.218 0 .416-.034.593-.102.178-.068.331-.16.461-.277a1.2 1.2 0 0 0 .301-.418c.07-.162.106-.336.106-.524a1.3 1.3 0 0 0-.106-.523 1.2 1.2 0 0 0-.3-.418 1.461 1.461 0 0 0-.462-.277 1.651 1.651 0 0 0-.593-.102c-.22 0-.417.034-.594.102a1.46 1.46 0 0 0-.461.277 1.2 1.2 0 0 0-.3.418 1.284 1.284 0 0 0-.106.523z"/></symbol><symbol viewBox="0 0 16 16" id="question-o" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zm-.778-4.151c0-.301.014-.575.044-.82a3.2 3.2 0 0 1 .154-.68c.073-.208.17-.4.294-.575.123-.176.278-.343.465-.503a4.81 4.81 0 0 0 .755-.758c.185-.242.277-.506.277-.793 0-.356-.074-.617-.222-.783-.148-.166-.37-.25-.667-.25a.92.92 0 0 0-.342.065.806.806 0 0 0-.29.199 1.04 1.04 0 0 0-.209.345 1.5 1.5 0 0 0-.088.506H5.082c.005-.51.092-.948.263-1.313.171-.364.401-.664.69-.899.29-.234.63-.406 1.023-.516a4.66 4.66 0 0 1 1.264-.164c.497 0 .944.058 1.34.174.397.117.733.289 1.008.517.276.227.487.51.633.847.146.337.218.727.218 1.17 0 .295-.042.56-.126.792a2.52 2.52 0 0 1-.349.65 4.4 4.4 0 0 1-.523.584c-.2.19-.414.389-.642.598a2.73 2.73 0 0 0-.332.349c-.089.114-.16.233-.212.359a1.868 1.868 0 0 0-.116.41 3.39 3.39 0 0 0-.044.489H7.222zm-.28 2.078c0-.164.03-.317.092-.458a1.05 1.05 0 0 1 .263-.366c.114-.103.248-.183.403-.243a1.45 1.45 0 0 1 .52-.089c.191 0 .364.03.52.09.154.059.289.14.403.242.114.103.201.224.263.366.061.141.092.294.092.458 0 .164-.03.316-.092.458a1.05 1.05 0 0 1-.263.365 1.278 1.278 0 0 1-.404.243 1.43 1.43 0 0 1-.52.089c-.19 0-.364-.03-.519-.089-.155-.06-.29-.14-.403-.243a1.05 1.05 0 0 1-.263-.365 1.135 1.135 0 0 1-.093-.458z"/></symbol><symbol viewBox="0 0 16 16" id="quote" xmlns="http://www.w3.org/2000/svg"><path d="M15 3v8a3 3 0 0 1-3 3 1 1 0 0 1 0-2 1 1 0 0 0 1-1V9h-2a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h3a1 1 0 0 1 1 1zM7 3v8a3 3 0 0 1-3 3 1 1 0 0 1 0-2 1 1 0 0 0 1-1V9H3a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h3a1 1 0 0 1 1 1z"/></symbol><symbol viewBox="0 0 16 16" id="redo" xmlns="http://www.w3.org/2000/svg"><path d="M4.666 4.423a5 5 0 1 1-.203 6.944 1 1 0 1 0-1.478 1.347 7 7 0 1 0 .12-9.556L1.842 2.137a.5.5 0 0 0-.815.385L1 7.26a.5.5 0 0 0 .607.492l4.629-1.013a.5.5 0 0 0 .207-.877L4.666 4.423z"/></symbol><symbol viewBox="0 0 16 16" id="remove" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M2 3a1 1 0 1 1 0-2h12a1 1 0 0 1 0 2v10a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V3zm3-2a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1H5zM4 3v10a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V3H4zm2.5 2a.5.5 0 0 1 .5.5v6a.5.5 0 1 1-1 0v-6a.5.5 0 0 1 .5-.5zm3 0a.5.5 0 0 1 .5.5v6a.5.5 0 1 1-1 0v-6a.5.5 0 0 1 .5-.5z"/></symbol><symbol viewBox="0 0 16 16" id="repeat" xmlns="http://www.w3.org/2000/svg"><path d="M11.494 4.423a5 5 0 1 0 .203 6.944 1 1 0 1 1 1.478 1.347 7 7 0 1 1-.12-9.556l1.262-1.021a.5.5 0 0 1 .815.385l.028 4.738a.5.5 0 0 1-.607.492L9.924 6.739a.5.5 0 0 1-.207-.877l1.777-1.439z"/></symbol><symbol viewBox="0 0 16 16" id="retry" xmlns="http://www.w3.org/2000/svg"><path d="M4.009 6.958a4 4 0 0 0 5.283 4.775 1 1 0 0 1 .712 1.87A6 6 0 0 1 2.077 6.44l-.741-.2a.5.5 0 0 1-.12-.915L3.41 4.058a.5.5 0 0 1 .683.183l1.268 2.196a.5.5 0 0 1-.563.733l-.79-.212zm7.777 2.084a4 4 0 0 0-5.284-4.775 1 1 0 0 1-.711-1.87 6 6 0 0 1 7.927 7.162l.74.2a.5.5 0 0 1 .121.915l-2.196 1.268a.5.5 0 0 1-.683-.183l-1.267-2.196a.5.5 0 0 1 .562-.733l.79.212z"/></symbol><symbol viewBox="0 0 16 16" id="scale" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M13.99 9a.792.792 0 0 0-.078-.231L13 7l-.912 1.769a.791.791 0 0 0-.077.231h1.978zm-10 0a.792.792 0 0 0-.078-.231L3 7l-.912 1.769A.791.791 0 0 0 2.011 9h1.978zM2 0h12a1 1 0 0 1 0 2H2a1 1 0 1 1 0-2zm3 14h6a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2zM8 4a1 1 0 0 1 1 1v9H7V5a1 1 0 0 1 1-1zm-4.53-.714l2.265 4.735c.68 1.42.006 3.091-1.504 3.73A3.161 3.161 0 0 1 3 12c-1.657 0-3-1.263-3-2.821 0-.4.09-.794.264-1.158L2.53 3.286a.53.53 0 0 1 .94 0zm10 0l2.265 4.735c.68 1.42.006 3.091-1.504 3.73A3.161 3.161 0 0 1 13 12c-1.657 0-3-1.263-3-2.821 0-.4.09-.794.264-1.158l2.266-4.735a.53.53 0 0 1 .94 0z"/></symbol><symbol viewBox="0 0 16 16" id="screen-full" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M14 14v-2a1 1 0 0 1 2 0v3a.997.997 0 0 1-1 1h-3a1 1 0 0 1 0-2h2zM2 14v-2a1 1 0 0 0-2 0v3a1 1 0 0 0 1 1h3a1 1 0 0 0 0-2H2zM15.707.293A.997.997 0 0 1 16 1v3a1 1 0 0 1-2 0V2h-2a1 1 0 0 1 0-2h3c.276 0 .526.112.707.293zM2 2v2a1 1 0 1 1-2 0V1a.997.997 0 0 1 1-1h3a1 1 0 1 1 0 2H2zm4 4h4a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1z"/></symbol><symbol viewBox="0 0 16 16" id="screen-normal" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M3 3V1a1 1 0 1 1 2 0v3a.997.997 0 0 1-1 1H1a1 1 0 1 1 0-2h2zm10 0h2a1 1 0 0 1 0 2h-3a.997.997 0 0 1-1-1V1a1 1 0 0 1 2 0v2zM3 13H1a1 1 0 0 1 0-2h3a.997.997 0 0 1 1 1v3a1 1 0 0 1-2 0v-2zm10 0v2a1 1 0 0 1-2 0v-3a.997.997 0 0 1 1-1h3a1 1 0 0 1 0 2h-2zM6.5 7h3a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5z"/></symbol><symbol viewBox="0 0 16 16" id="search" xmlns="http://www.w3.org/2000/svg"><path d="M8.853 8.854a3.5 3.5 0 1 0-4.95-4.95 3.5 3.5 0 0 0 4.95 4.95zm.207 2.328a5.5 5.5 0 1 1 2.121-2.121l3.329 3.328a1.5 1.5 0 0 1-2.121 2.121L9.06 11.182z"/></symbol><symbol viewBox="0 0 16 16" id="settings" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M2.415 5.803L1.317 4.084A.5.5 0 0 1 1.35 3.5l.805-.994a.5.5 0 0 1 .564-.153l1.878.704a5.975 5.975 0 0 1 1.65-.797L6.885.342A.5.5 0 0 1 7.36 0h1.28a.5.5 0 0 1 .474.342l.639 1.918a5.97 5.97 0 0 1 1.65.797l1.877-.704a.5.5 0 0 1 .565.153l.805.994a.5.5 0 0 1 .032.584l-1.097 1.719c.217.551.354 1.143.399 1.76l1.731 1.058a.5.5 0 0 1 .227.54l-.288 1.246a.5.5 0 0 1-.44.385l-2.008.19a6.026 6.026 0 0 1-1.142 1.431l.265 1.995a.5.5 0 0 1-.277.516l-1.15.56a.5.5 0 0 1-.576-.1l-1.424-1.452a6.047 6.047 0 0 1-1.804 0l-1.425 1.453a.5.5 0 0 1-.576.1l-1.15-.561a.5.5 0 0 1-.276-.516l.265-1.995a6.026 6.026 0 0 1-1.143-1.43l-2.008-.191a.5.5 0 0 1-.44-.385L.058 9.16a.5.5 0 0 1 .226-.539l1.732-1.058a5.968 5.968 0 0 1 .399-1.76zM8 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/></symbol><symbol viewBox="0 0 16 16" id="shield" xmlns="http://www.w3.org/2000/svg"><path d="M4 0h8a3 3 0 0 1 3 3v7.186a3 3 0 0 1-1.426 2.554l-4 2.465a3 3 0 0 1-3.148 0l-4-2.465A3 3 0 0 1 1 10.186V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v7.186a1 1 0 0 0 .475.852l4 2.464a1 1 0 0 0 1.05 0l4-2.464a1 1 0 0 0 .475-.852V3a1 1 0 0 0-1-1H4zm0 1.5a.5.5 0 0 1 .5-.5h4v8.837a.5.5 0 0 1-.753.431l-3.5-2.052A.5.5 0 0 1 4 9.785V3.5z"/></symbol><symbol viewBox="0 0 16 16" id="slight-frown" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zm-2.163-3.275a2.499 2.499 0 0 1 4.343.03.5.5 0 0 1-.871.49 1.5 1.5 0 0 0-2.607-.018.5.5 0 1 1-.865-.502zM5 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm6 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="slight-smile" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zM5 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm6 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm-5.163 2.254a.5.5 0 1 1 .865-.502 1.499 1.499 0 0 0 2.607-.018.5.5 0 1 1 .871.49 2.499 2.499 0 0 1-4.343.03z"/></symbol><symbol viewBox="0 0 16 16" id="smile" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zM6.18 6.27a.5.5 0 0 1-.873.487.5.5 0 0 0-.872-.003.5.5 0 1 1-.87-.495 1.5 1.5 0 0 1 2.616.012zm6 0a.5.5 0 1 1-.873.487.5.5 0 0 0-.872-.003.5.5 0 1 1-.87-.495 1.5 1.5 0 0 1 2.616.012zM5 9a3 3 0 0 0 6 0H5z"/></symbol><symbol viewBox="0 0 16 16" id="smiley" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zM5 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm6 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zM5 9h6a3 3 0 0 1-6 0z"/></symbol><symbol viewBox="0 0 16 16" id="snippet" xmlns="http://www.w3.org/2000/svg"><path d="M10.67 9.31a3.001 3.001 0 0 1 2.062 5.546 3 3 0 0 1-3.771-4.559 1.007 1.007 0 0 1-.095-.137l-4.5-7.794a1 1 0 0 1 1.732-1l4.5 7.794c.028.05.052.1.071.15zm-3.283.35l-.289.5c-.028.05-.06.095-.095.137a3.001 3.001 0 0 1-3.77 4.56A3 3 0 0 1 5.294 9.31c.02-.051.043-.102.071-.15l.866-1.5 1.155 2zm2.31-4l-1.156-2 1.325-2.294a1 1 0 0 1 1.732 1L9.696 5.66zm-5.465 7.464a1 1 0 1 0 1-1.732 1 1 0 0 0-1 1.732zm7.5 0a1 1 0 1 0-1-1.732 1 1 0 0 0 1 1.732z"/></symbol><symbol viewBox="0 0 16 16" id="spam" xmlns="http://www.w3.org/2000/svg"><path d="M8.75.433l5.428 3.134a1.5 1.5 0 0 1 .75 1.299v6.268a1.5 1.5 0 0 1-.75 1.299L8.75 15.567a1.5 1.5 0 0 1-1.5 0l-5.428-3.134a1.5 1.5 0 0 1-.75-1.299V4.866a1.5 1.5 0 0 1 .75-1.299L7.25.433a1.5 1.5 0 0 1 1.5 0zM3.072 5.155v5.69L8 13.691l4.928-2.846v-5.69L8 2.309 3.072 5.155zM8 4a1 1 0 0 1 1 1v3a1 1 0 1 1-2 0V5a1 1 0 0 1 1-1zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="star" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7.609 14.394l-3.465 1.473a1 1 0 0 1-1.39-.989l.276-4.024a1 1 0 0 0-.219-.694L.303 7.037A1 1 0 0 1 .83 5.443l3.715-.964a1 1 0 0 0 .609-.457L7.14.682a1 1 0 0 1 1.72 0l1.985 3.34a1 1 0 0 0 .609.457l3.715.964a1 1 0 0 1 .528 1.594L13.19 10.16a1 1 0 0 0-.219.694l.275 4.024a1 1 0 0 1-1.389.989l-3.465-1.473a1 1 0 0 0-.782 0z"/></symbol><symbol viewBox="0 0 16 16" id="star-o" xmlns="http://www.w3.org/2000/svg"><path d="M10.975 10.99a3 3 0 0 1 .655-2.083l1.54-1.916-2.219-.576a3 3 0 0 1-1.825-1.37L8 3.15 6.874 5.044a3 3 0 0 1-1.825 1.371l-2.218.576 1.54 1.916a3 3 0 0 1 .654 2.083l-.165 2.4 1.965-.836a3 3 0 0 1 2.348 0l1.965.836-.164-2.399zM7.61 14.394l-3.465 1.473a1 1 0 0 1-1.39-.989l.276-4.024a1 1 0 0 0-.219-.694L.303 7.037A1 1 0 0 1 .83 5.443l3.715-.964a1 1 0 0 0 .609-.457L7.14.682a1 1 0 0 1 1.72 0l1.985 3.34a1 1 0 0 0 .609.457l3.715.964a1 1 0 0 1 .528 1.594L13.19 10.16a1 1 0 0 0-.219.694l.275 4.024a1 1 0 0 1-1.389.989l-3.465-1.473a1 1 0 0 0-.782 0z"/></symbol><symbol viewBox="0 0 16 16" id="stop" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M2 0h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2z"/></symbol><symbol viewBox="0 0 16 16" id="talic" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M6 0h7a1 1 0 0 1 0 2H6a1 1 0 1 1 0-2zm2 2h3L8 14H5L8 2zM3 14h7a1 1 0 0 1 0 2H3a1 1 0 0 1 0-2z"/></symbol><symbol viewBox="0 0 16 16" id="task-done" xmlns="http://www.w3.org/2000/svg"><path d="M7.536 8.657l2.828-2.829a1 1 0 0 1 1.414 1.415l-3.535 3.535a.997.997 0 0 1-1.415 0l-2.12-2.121A1 1 0 0 1 6.12 7.243l1.415 1.414zM3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3z"/></symbol><symbol viewBox="0 0 16 16" id="template" xmlns="http://www.w3.org/2000/svg"><path d="M3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3zm.8 2h2.4a.8.8 0 0 1 .8.8v1.4a.8.8 0 0 1-.8.8H3.8a.8.8 0 0 1-.8-.8V4.8a.8.8 0 0 1 .8-.8zm4.7 0h4a.5.5 0 1 1 0 1h-4a.5.5 0 0 1 0-1zm0 2h4a.5.5 0 1 1 0 1h-4a.5.5 0 0 1 0-1zm-5 3h9a.5.5 0 1 1 0 1h-9a.5.5 0 0 1 0-1zm0 2h9a.5.5 0 1 1 0 1h-9a.5.5 0 1 1 0-1z"/></symbol><symbol viewBox="0 0 16 16" id="thump-down" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8.33 11h5.282a2 2 0 0 0 1.963-2.38l-.563-2.905a3 3 0 0 0-.243-.732l-1.103-2.286A3 3 0 0 0 10.964 1H7a3 3 0 0 0-3 3v6.3a2 2 0 0 0 .436 1.247l3.11 3.9a.632.632 0 0 0 .941.053l.137-.137a1 1 0 0 0 .28-.87L8.329 11zM1 10h2V3H1a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1z"/></symbol><symbol viewBox="0 0 16 16" id="thump-up" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8.33 5h5.282a2 2 0 0 1 1.963 2.38l-.563 2.905a3 3 0 0 1-.243.732l-1.103 2.286A3 3 0 0 1 10.964 15H7a3 3 0 0 1-3-3V5.7a2 2 0 0 1 .436-1.247l3.11-3.9A.632.632 0 0 1 8.487.5l.137.137a1 1 0 0 1 .28.87L8.329 5zM1 6h2v7H1a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1z"/></symbol><symbol viewBox="0 0 16 16" id="timer" xmlns="http://www.w3.org/2000/svg"><path d="M12.022 3.27l.77-.77a1 1 0 0 1 1.415 1.414l-.728.729a7 7 0 1 1-1.456-1.372zM8 14A5 5 0 1 0 8 4a5 5 0 0 0 0 10zm0-9a1 1 0 0 1 1 1v2a1 1 0 1 1-2 0V6a1 1 0 0 1 1-1zM6 0h4a1 1 0 0 1 0 2H6a1 1 0 1 1 0-2z"/></symbol><symbol viewBox="0 0 16 16" id="todo-add" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 4V2a1 1 0 0 1 2 0v2h2a1 1 0 0 1 0 2h-2v2a1 1 0 0 1-2 0V6H8a1 1 0 1 1 0-2h2zm2 7a1 1 0 0 1 2 0v2a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3h2a1 1 0 1 1 0 2H3a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-2z"/></symbol><symbol viewBox="0 0 16 16" id="todo-done" xmlns="http://www.w3.org/2000/svg"><path d="M8.243 7.485l4.95-4.95a1 1 0 1 1 1.414 1.415L8.95 9.607a.997.997 0 0 1-1.414 0L4.707 6.778a1 1 0 0 1 1.414-1.414l2.122 2.121zM12 11a1 1 0 0 1 2 0v2a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3h2a1 1 0 1 1 0 2H3a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-2z"/></symbol><symbol viewBox="0 0 16 16" id="token" xmlns="http://www.w3.org/2000/svg"><path d="M3 2h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H3zm1 5a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="unapproval" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M11.95 8.536l1.06-1.061a1 1 0 0 1 1.415 1.414l-1.061 1.06 1.06 1.061a1 1 0 0 1-1.414 1.415l-1.06-1.061-1.06 1.06a1 1 0 1 1-1.415-1.414l1.06-1.06-1.06-1.06a1 1 0 0 1 1.414-1.415l1.06 1.06zm-3.768-.33c.006.503.201 1.006.586 1.39l.353.354-.353.353a2 2 0 1 0 2.828 2.829l.354-.354.047.048C11.964 14.363 11.527 15 6 15c-5.924 0-6-.78-6-2.52S.964 8 6 8c.834 0 1.557.074 2.182.205zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6z"/></symbol><symbol viewBox="0 0 16 16" id="unassignee" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M11 5h4a1 1 0 0 1 0 2h-4a1 1 0 0 1 0-2zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6zM6 15c-5.924 0-6-.78-6-2.52S.964 8 6 8s6 2.692 6 4.48c0 1.788-.076 2.52-6 2.52z"/></symbol><symbol viewBox="0 0 16 16" id="unlink" xmlns="http://www.w3.org/2000/svg"><path d="M11.295 8.845l-.659-1.664a1.78 1.78 0 0 0 .04-.04l1.415-1.414c.586-.586.654-1.468.152-1.97s-1.384-.434-1.97.152L8.859 5.323a1.781 1.781 0 0 0-.04.04l-1.664-.658c.141-.208.305-.408.491-.594l1.415-1.414c1.366-1.367 3.424-1.525 4.596-.354 1.171 1.172 1.013 3.23-.354 4.596L11.89 8.354c-.186.186-.386.35-.594.491zm-2.45 2.45a4.075 4.075 0 0 1-.491.594l-1.415 1.414c-1.366 1.367-3.424 1.525-4.596.354-1.171-1.172-1.013-3.23.354-4.596L4.11 7.646c.186-.186.386-.35.594-.491l.659 1.664a1.781 1.781 0 0 0-.04.04l-1.415 1.414c-.586.586-.654 1.468-.152 1.97s1.384.434 1.97-.152l1.414-1.414a1.78 1.78 0 0 0 .04-.04l1.664.658zm3.812-2.088h2a.5.5 0 0 1 .5.5v.05a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-.05a.5.5 0 0 1 .5-.5zm-.384 2.116l1.415 1.414a.5.5 0 0 1 0 .708l-.037.036a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 0-.707l.036-.037a.5.5 0 0 1 .707 0zm-2.823 1.09a.5.5 0 0 1 .5-.5h.052a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.5.5H9.95a.5.5 0 0 1-.5-.5v-2zm-2.748-9.16a.5.5 0 0 1-.5.5h-.05a.5.5 0 0 1-.5-.5v-2a.5.5 0 0 1 .5-.5h.05a.5.5 0 0 1 .5.5v2zm-2.116.383a.5.5 0 0 1 0 .707l-.036.036a.5.5 0 0 1-.707 0L2.428 2.965a.5.5 0 0 1 0-.707l.037-.036a.5.5 0 0 1 .707 0l1.414 1.414zm-1.09 2.823h-2a.5.5 0 0 1-.5-.5v-.051a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v.05a.5.5 0 0 1-.5.5z"/></symbol><symbol viewBox="0 0 16 16" id="user" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0 8c-6.888 0-6.976-.78-6.976-2.52S2.144 8 8 8s6.976 2.692 6.976 4.48c0 1.788-.088 2.52-6.976 2.52z"/></symbol><symbol viewBox="0 0 16 16" id="users" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10.521 8.01C15.103 8.19 16 10.755 16 12.48c0 1.533-.056 2.29-3.808 2.475.609-.54.808-1.331.808-2.475 0-1.911-.804-3.503-2.479-4.47zm-1.67-1.228A3.987 3.987 0 0 0 9.976 4a3.987 3.987 0 0 0-1.125-2.782 3 3 0 1 1 0 5.563zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6zM6 15c-5.924 0-6-.78-6-2.52S.964 8 6 8s6 2.692 6 4.48c0 1.788-.076 2.52-6 2.52z"/></symbol><symbol viewBox="0 0 16 16" id="volume-up" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M1 5h1v6H1a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1zm2 0l4.445-2.964A1 1 0 0 1 9 2.87v10.26a1 1 0 0 1-1.555.833L3 11V5zm10.283 7.89a.5.5 0 0 1-.66-.752A5.485 5.485 0 0 0 14.5 8c0-1.601-.687-3.09-1.865-4.128a.5.5 0 0 1 .661-.75A6.484 6.484 0 0 1 15.5 8a6.485 6.485 0 0 1-2.217 4.89zm-2.002-2.236a.5.5 0 1 1-.652-.758c.55-.472.871-1.157.871-1.896 0-.732-.315-1.411-.856-1.883a.5.5 0 0 1 .658-.753A3.492 3.492 0 0 1 12.5 8c0 1.033-.45 1.994-1.219 2.654z"/></symbol><symbol viewBox="0 0 16 16" id="warning" xmlns="http://www.w3.org/2000/svg"><path d="M15.34 10.479A3 3 0 0 1 12.756 15h-9.51A3 3 0 0 1 .66 10.479l4.755-8.083a3 3 0 0 1 5.172 0l4.755 8.083zm-6.478-7.07a1 1 0 0 0-1.724 0l-4.755 8.084A1 1 0 0 0 3.245 13h9.51a1 1 0 0 0 .862-1.507L8.862 3.41zM8 5a1 1 0 0 1 1 1v2a1 1 0 1 1-2 0V6a1 1 0 0 1 1-1zm0 7a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol><symbol viewBox="0 0 16 16" id="work" xmlns="http://www.w3.org/2000/svg"><path d="M12 3h1a3 3 0 0 1 3 3v7a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V6a3 3 0 0 1 3-3h1V2a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v1zM6 2v1h4V2H6zM3 5a1 1 0 0 0-1 1v7a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1H3zm1.5 1a.5.5 0 0 1 .5.5v6a.5.5 0 1 1-1 0v-6a.5.5 0 0 1 .5-.5zm7 0a.5.5 0 0 1 .5.5v6a.5.5 0 1 1-1 0v-6a.5.5 0 0 1 .5-.5z"/></symbol></svg>
\ No newline at end of file diff --git a/app/assets/images/sprite.symbol.html b/app/assets/images/sprite.symbol.html deleted file mode 100644 index d928d3f73b8..00000000000 --- a/app/assets/images/sprite.symbol.html +++ /dev/null @@ -1,3297 +0,0 @@ -<!DOCTYPE html> -<html lang="en" xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta charset="utf-8"/> - <meta http-equiv="X-UA-Compatible" content="IE=Edge"/> - <script src="https://rawgit.com/jonathantneal/svg4everybody/master/dist/svg4everybody.js"></script> - <script>svg4everybody();</script> - <title>SVG <symbol> sprite preview | svg-sprite</title> - <style>@charset "UTF-8";body{padding:0;margin:0;color:#666;background:#fafafa;font-family:Arial,Helvetica,sans-serif;font-size:1em;line-height:1.4}header{display:block;padding:3em 3em 2em 3em;background-color:#fff}header p{margin:2em 0 0 0}section{border-top:1px solid #eee;padding:2em 3em 0 3em}section ul{margin:0;padding:0}section li{display:inline;display:inline-block;background-color:#fff;position:relative;margin:0 2em 2em 0;vertical-align:top;border:1px solid #ccc;padding:1em 1em 3em 1em;cursor:default}.icon-box{margin:0;width:144px;height:144px;position:relative;background:#ccc url("data:image/gif;base64,R0lGODlhDAAMAIAAAMzMzP///yH/C1hNUCBEYXRhWE1QPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS4wLWMwNjEgNjQuMTQwOTQ5LCAyMDEwLzEyLzA3LTEwOjU3OjAxICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1LjEgV2luZG93cyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDozQjk4OTI0MUY5NTIxMUUyQkJDMEI5NEFEM0Y1QTYwQyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDozQjk4OTI0MkY5NTIxMUUyQkJDMEI5NEFEM0Y1QTYwQyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjNCOTg5MjNGRjk1MjExRTJCQkMwQjk0QUQzRjVBNjBDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjNCOTg5MjQwRjk1MjExRTJCQkMwQjk0QUQzRjVBNjBDIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Af/+/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl5aVlJOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0c3JxcG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlFQT05NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIBwYFBAMCAQAAIfkEAAAAAAAsAAAAAAwADAAAAhaEH6mHmmzcgzJAUG/NVGrfOZ8YLlABADs=") top left repeat;border:1px solid #ccc;display:table-cell;vertical-align:middle;text-align:center}.icon{display:inline;display:inline-block}h1{margin-top:0}h2{margin:0;padding:0;font-size:1em;font-weight:normal;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;position:absolute;left:1em;right:1em;bottom:1em}footer{display:block;margin:0;padding:0 3em 3em 3em}footer p{margin:0;font-size:.7em}footer a{color:#0f7595;margin-left:0}</style> - -<!-- - -Sprite shape dimensions -==================================================================================================== -You will need to set the sprite shape dimensions via CSS when you use them as inline SVG, otherwise -they would become a huge 100% in size. You may use the following dimension classes for doing so. -They might well be outsourced to an external stylesheet of course. - ---> - -<style type="text/css"> - .svg-abuse-dims { width: 16px; height: 16px; } - .svg-account-dims { width: 16px; height: 16px; } - .svg-admin-dims { width: 16px; height: 16px; } - .svg-angle-double-left-dims { width: 16px; height: 16px; } - .svg-angle-down-dims { width: 16px; height: 16px; } - .svg-angle-left-dims { width: 16px; height: 16px; } - .svg-angle-right-dims { width: 16px; height: 16px; } - .svg-angle-up-dims { width: 16px; height: 16px; } - .svg-appearance-dims { width: 16px; height: 16px; } - .svg-applications-dims { width: 16px; height: 16px; } - .svg-approval-dims { width: 16px; height: 16px; } - .svg-arrow-right-dims { width: 16px; height: 16px; } - .svg-assignee-dims { width: 16px; height: 16px; } - .svg-bold-dims { width: 16px; height: 16px; } - .svg-book-dims { width: 16px; height: 16px; } - .svg-branch-dims { width: 16px; height: 16px; } - .svg-calendar-dims { width: 16px; height: 16px; } - .svg-cancel-dims { width: 16px; height: 16px; } - .svg-chevron-down-dims { width: 16px; height: 16px; } - .svg-chevron-left-dims { width: 16px; height: 16px; } - .svg-chevron-right-dims { width: 16px; height: 16px; } - .svg-chevron-up-dims { width: 16px; height: 16px; } - .svg-clock-dims { width: 16px; height: 16px; } - .svg-code-dims { width: 16px; height: 16px; } - .svg-comment-dims { width: 16px; height: 16px; } - .svg-comment-dots-dims { width: 16px; height: 16px; } - .svg-comment-next-dims { width: 16px; height: 16px; } - .svg-comments-dims { width: 16px; height: 16px; } - .svg-commit-dims { width: 16px; height: 16px; } - .svg-credit-card-dims { width: 16px; height: 16px; } - .svg-disk-dims { width: 16px; height: 16px; } - .svg-doc_code-dims { width: 16px; height: 16px; } - .svg-doc_image-dims { width: 16px; height: 16px; } - .svg-doc_text-dims { width: 16px; height: 16px; } - .svg-download-dims { width: 16px; height: 16px; } - .svg-duplicate-dims { width: 16px; height: 16px; } - .svg-earth-dims { width: 16px; height: 16px; } - .svg-eye-dims { width: 16px; height: 16px; } - .svg-eye-slash-dims { width: 16px; height: 16px; } - .svg-file-additions-dims { width: 16px; height: 16px; } - .svg-file-deletion-dims { width: 16px; height: 16px; } - .svg-file-modified-dims { width: 16px; height: 16px; } - .svg-filter-dims { width: 16px; height: 16px; } - .svg-folder-dims { width: 16px; height: 16px; } - .svg-fork-dims { width: 16px; height: 16px; } - .svg-git-merge-dims { width: 16px; height: 16px; } - .svg-group-dims { width: 16px; height: 16px; } - .svg-history-dims { width: 16px; height: 16px; } - .svg-home-dims { width: 16px; height: 16px; } - .svg-hook-dims { width: 16px; height: 16px; } - .svg-issue-block-dims { width: 16px; height: 16px; } - .svg-issue-child-dims { width: 16px; height: 16px; } - .svg-issue-close-dims { width: 16px; height: 16px; } - .svg-issue-duplicate-dims { width: 16px; height: 16px; } - .svg-issue-new-dims { width: 16px; height: 16px; } - .svg-issue-open-dims { width: 16px; height: 16px; } - .svg-issue-open-m-dims { width: 16px; height: 16px; } - .svg-issue-parent-dims { width: 16px; height: 16px; } - .svg-issues-dims { width: 16px; height: 16px; } - .svg-key-dims { width: 16px; height: 16px; } - .svg-key-2-dims { width: 16px; height: 16px; } - .svg-label-dims { width: 16px; height: 16px; } - .svg-labels-dims { width: 16px; height: 16px; } - .svg-leave-dims { width: 16px; height: 16px; } - .svg-level-up-dims { width: 16px; height: 16px; } - .svg-license-dims { width: 16px; height: 16px; } - .svg-link-dims { width: 16px; height: 16px; } - .svg-list-bulleted-dims { width: 16px; height: 16px; } - .svg-list-numbered-dims { width: 16px; height: 16px; } - .svg-location-dims { width: 16px; height: 16px; } - .svg-location-dot-dims { width: 16px; height: 16px; } - .svg-lock-dims { width: 16px; height: 16px; } - .svg-lock-open-dims { width: 16px; height: 16px; } - .svg-log-dims { width: 16px; height: 16px; } - .svg-mail-dims { width: 16px; height: 16px; } - .svg-merge-request-close-dims { width: 16px; height: 16px; } - .svg-merge-request-close-m-dims { width: 16px; height: 16px; } - .svg-messages-dims { width: 16px; height: 16px; } - .svg-mobile-issue-close-dims { width: 16px; height: 16px; } - .svg-monitor-dims { width: 16px; height: 16px; } - .svg-more-dims { width: 16px; height: 16px; } - .svg-notifications-dims { width: 16px; height: 16px; } - .svg-notifications-off-dims { width: 16px; height: 16px; } - .svg-overview-dims { width: 16px; height: 16px; } - .svg-pencil-dims { width: 16px; height: 16px; } - .svg-pipeline-dims { width: 16px; height: 16px; } - .svg-play-dims { width: 16px; height: 16px; } - .svg-plus-dims { width: 16px; height: 16px; } - .svg-plus-square-dims { width: 16px; height: 16px; } - .svg-plus-square-o-dims { width: 16px; height: 16px; } - .svg-preferences-dims { width: 16px; height: 16px; } - .svg-profile-dims { width: 16px; height: 16px; } - .svg-project-dims { width: 16px; height: 16px; } - .svg-push-rules-dims { width: 16px; height: 16px; } - .svg-question-dims { width: 16px; height: 16px; } - .svg-question-o-dims { width: 16px; height: 16px; } - .svg-quote-dims { width: 16px; height: 16px; } - .svg-redo-dims { width: 16px; height: 16px; } - .svg-remove-dims { width: 16px; height: 16px; } - .svg-repeat-dims { width: 16px; height: 16px; } - .svg-retry-dims { width: 16px; height: 16px; } - .svg-scale-dims { width: 16px; height: 16px; } - .svg-screen-full-dims { width: 16px; height: 16px; } - .svg-screen-normal-dims { width: 16px; height: 16px; } - .svg-search-dims { width: 16px; height: 16px; } - .svg-settings-dims { width: 16px; height: 16px; } - .svg-shield-dims { width: 16px; height: 16px; } - .svg-slight-frown-dims { width: 16px; height: 16px; } - .svg-slight-smile-dims { width: 16px; height: 16px; } - .svg-smile-dims { width: 16px; height: 16px; } - .svg-smiley-dims { width: 16px; height: 16px; } - .svg-snippet-dims { width: 16px; height: 16px; } - .svg-spam-dims { width: 16px; height: 16px; } - .svg-star-dims { width: 16px; height: 16px; } - .svg-star-o-dims { width: 16px; height: 16px; } - .svg-stop-dims { width: 16px; height: 16px; } - .svg-talic-dims { width: 16px; height: 16px; } - .svg-task-done-dims { width: 16px; height: 16px; } - .svg-template-dims { width: 16px; height: 16px; } - .svg-thump-down-dims { width: 16px; height: 16px; } - .svg-thump-up-dims { width: 16px; height: 16px; } - .svg-timer-dims { width: 16px; height: 16px; } - .svg-todo-add-dims { width: 16px; height: 16px; } - .svg-todo-done-dims { width: 16px; height: 16px; } - .svg-token-dims { width: 16px; height: 16px; } - .svg-unapproval-dims { width: 16px; height: 16px; } - .svg-unassignee-dims { width: 16px; height: 16px; } - .svg-unlink-dims { width: 16px; height: 16px; } - .svg-user-dims { width: 16px; height: 16px; } - .svg-users-dims { width: 16px; height: 16px; } - .svg-volume-up-dims { width: 16px; height: 16px; } - .svg-warning-dims { width: 16px; height: 16px; } - .svg-work-dims { width: 16px; height: 16px; } -</style> -<!-- -==================================================================================================== ---> - - </head> - <body> - -<!-- - -Inline <symbol> SVG sprite -==================================================================================================== -This is an inlined version of the generated SVG sprite. The single images may be <use>d everywhere -below within this document. Please see - - https://github.com/jkphl/svg-sprite/blob/master/docs/configuration.md#defs--symbol-mode - -for further details on how to create this embeddable sprite variant. - ---> - -<svg width="0" height="0" style="position:absolute"> - <symbol viewBox="0 0 16 16" id="abuse" xmlns="http://www.w3.org/2000/svg"><path d="M11.408.328l4.029 3.222A1.5 1.5 0 0 1 16 4.72v6.555a1.5 1.5 0 0 1-.563 1.171l-4.026 3.224a1.5 1.5 0 0 1-.937.329H5.529a1.5 1.5 0 0 1-.937-.328L.563 12.45A1.5 1.5 0 0 1 0 11.28V4.724a1.5 1.5 0 0 1 .563-1.171L4.589.329A1.5 1.5 0 0 1 5.526 0h4.945c.34 0 .67.116.937.328zM10.296 2H5.702L2 4.964v6.074L5.704 14h4.594L14 11.036V4.962L10.296 2zM8 4a1 1 0 0 1 1 1v3a1 1 0 1 1-2 0V5a1 1 0 0 1 1-1zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol> - <symbol viewBox="0 0 16 16" id="account" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M9.195 9.965l-.568-.875a.25.25 0 0 1 .015-.294l.405-.5a.25.25 0 0 1 .283-.075l.938.36c.257-.183.543-.325.851-.42l.322-.988A.25.25 0 0 1 11.679 7h.642a.25.25 0 0 1 .238.173l.322.988c.308.095.594.237.851.42l.938-.36a.25.25 0 0 1 .283.076l.405.5a.25.25 0 0 1 .015.293l-.568.875c.113.297.18.616.193.95l.898.54a.25.25 0 0 1 .115.27l-.144.626a.25.25 0 0 1-.222.193l-1.115.098a3.015 3.015 0 0 1-.512.608l.165 1.18a.25.25 0 0 1-.138.259l-.577.281a.25.25 0 0 1-.29-.05l-.874-.905a3.035 3.035 0 0 1-.608 0l-.875.904a.25.25 0 0 1-.289.051l-.577-.281a.25.25 0 0 1-.138-.26l.165-1.18a3.015 3.015 0 0 1-.512-.607l-1.115-.098a.25.25 0 0 1-.222-.193l-.144-.626a.25.25 0 0 1 .115-.27l.898-.54c.013-.334.08-.653.193-.95zM6.789 8.023A12.845 12.845 0 0 0 6 8c-5.036 0-6 2.74-6 4.48C0 14.22.076 15 6 15c.553 0 1.055-.006 1.51-.02A5.977 5.977 0 0 1 6 11c0-1.083.287-2.1.79-2.977zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6zM12 12a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol> - <symbol viewBox="0 0 16 16" id="admin" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M13.162 2.5a3.5 3.5 0 0 1-3.163 5.479L6.08 14.766a1.5 1.5 0 0 1-2.598-1.5L7.4 6.479A3.5 3.5 0 0 1 10.564 1L8.9 3.88l2.599 1.5 1.663-2.88zm-8.63 11.949a.5.5 0 1 0 .5-.866.5.5 0 0 0-.5.866z"/></symbol> - <symbol viewBox="0 0 16 16" id="angle-double-left" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10.414 7.95l4.243-4.243a1 1 0 0 0-1.414-1.414l-4.95 4.95a.997.997 0 0 0 0 1.414l4.95 4.95a1 1 0 1 0 1.414-1.415L10.414 7.95zm-7 0l4.243-4.243a1 1 0 0 0-1.414-1.414l-4.95 4.95a.997.997 0 0 0 0 1.414l4.95 4.95a1 1 0 0 0 1.414-1.415L3.414 7.95z"/></symbol> - <symbol viewBox="0 0 16 16" id="angle-down" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8 10.243l-4.95-4.95a1 1 0 0 0-1.414 1.414l5.657 5.657a.997.997 0 0 0 1.414 0l5.657-5.657a1 1 0 0 0-1.414-1.414L8 10.243z"/></symbol> - <symbol viewBox="0 0 16 16" id="angle-left" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M5.757 8l4.95-4.95a1 1 0 1 0-1.414-1.414L3.636 7.293a.997.997 0 0 0 0 1.414l5.657 5.657a1 1 0 0 0 1.414-1.414L5.757 8z"/></symbol> - <symbol viewBox="0 0 16 16" id="angle-right" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10.243 8l-4.95-4.95a1 1 0 0 1 1.414-1.414l5.657 5.657a.997.997 0 0 1 0 1.414l-5.657 5.657a1 1 0 0 1-1.414-1.414L10.243 8z"/></symbol> - <symbol viewBox="0 0 16 16" id="angle-up" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8 6.757l-4.95 4.95a1 1 0 1 1-1.414-1.414l5.657-5.657a.997.997 0 0 1 1.414 0l5.657 5.657a1 1 0 0 1-1.414 1.414L8 6.757z"/></symbol> - <symbol viewBox="0 0 16 16" id="appearance" xmlns="http://www.w3.org/2000/svg"><path d="M11.161 12.456l.232.121c.1.053.175.094.249.137.53.318.844.75.857 1.402.012 1.397-1.116 1.756-3.12 1.858a23.85 23.85 0 0 1-1.38.026A8 8 0 0 1 0 8a8 8 0 0 1 8-8c4.417 0 7.998 3.582 7.998 7.977.06 2.621-1.312 3.586-4.48 3.648-.602.008-1.068.043-1.4.104.228.192.598.47 1.043.727zm-3.287-.943c-.019-1.495 1.228-1.856 3.611-1.888C13.67 9.582 14.028 9.33 13.998 8A6 6 0 1 0 8 14c.603 0 .91-.004 1.277-.023a9.7 9.7 0 0 0 .478-.035c-1.172-.738-1.868-1.47-1.88-2.43zM6 5a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm6 3a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm-2-3a1 1 0 1 1 0-2 1 1 0 0 1 0 2zM4 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol> - <symbol viewBox="0 0 16 16" id="applications" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M1 0h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1V1a1 1 0 0 1 1-1zm0 6h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1zm6-6h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V1a1 1 0 0 1 1-1zm0 1v2h2V1H7zm0 5h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1zm6-6h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1V1a1 1 0 0 1 1-1zm0 6h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1zm0 1v2h2V7h-2zM1 12h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1zm0 1v2h2v-2H1zm6-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1zm6 0h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1z"/></symbol> - <symbol viewBox="0 0 16 16" id="approval" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10.536 10.657l2.828-2.829a1 1 0 0 1 1.414 1.415l-3.535 3.535a.997.997 0 0 1-1.415 0l-2.12-2.121A1 1 0 1 1 9.12 9.243l1.415 1.414zM7.632 8.109A2 2 0 0 0 7 11.364l2.121 2.121a1.996 1.996 0 0 0 2.807.021C11.686 14.554 10.627 15 6 15c-5.924 0-6-.78-6-2.52S.964 8 6 8c.6 0 1.142.038 1.632.109zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6z"/></symbol> - <symbol viewBox="0 0 16 16" id="arrow-right" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M9 6H2a2 2 0 1 0 0 4h7v2.586a1 1 0 0 0 1.707.707l4.586-4.586a1 1 0 0 0 0-1.414l-4.586-4.586A1 1 0 0 0 9 3.414V6z"/></symbol> - <symbol viewBox="0 0 16 16" id="assignee" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M12 5V4a1 1 0 0 1 2 0v1h1a1 1 0 0 1 0 2h-1v1a1 1 0 0 1-2 0V7h-1a1 1 0 0 1 0-2h1zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6zM6 15c-5.924 0-6-.78-6-2.52S.964 8 6 8s6 2.692 6 4.48c0 1.788-.076 2.52-6 2.52z"/></symbol> - <symbol viewBox="0 0 16 16" id="bold" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M2 15V1a1 1 0 0 1 1-1h4.604c.93 0 1.762.088 2.495.264.733.176 1.353.445 1.863.807.509.363.897.82 1.164 1.369.268.549.401 1.197.401 1.945 0 .366-.045.718-.137 1.055-.091.337-.23.652-.417.945a3.453 3.453 0 0 1-.71.796 3.645 3.645 0 0 1-1.021.588c.469.117.87.295 1.203.533.333.238.608.515.824.83.216.315.374.657.473 1.027.099.37.148.75.148 1.138 0 1.553-.5 2.725-1.5 3.516-1 .791-2.423 1.187-4.27 1.187H3a1 1 0 0 1-1-1zm3.297-5.967v4.319H8.12c.425 0 .791-.053 1.099-.16.307-.106.564-.252.769-.44.205-.186.357-.406.456-.659.099-.252.148-.529.148-.83a3.04 3.04 0 0 0-.131-.928 1.78 1.78 0 0 0-.413-.703 1.8 1.8 0 0 0-.73-.445c-.3-.103-.66-.154-1.077-.154H5.297zm0-2.33h2.44c.842-.014 1.468-.192 1.878-.533.41-.34.616-.826.616-1.456 0-.725-.21-1.247-.632-1.566-.421-.318-1.086-.478-1.995-.478H5.297v4.033z"/></symbol> - <symbol viewBox="0 0 16 16" id="book" xmlns="http://www.w3.org/2000/svg"><path d="M7 2H5a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2v4.191a.5.5 0 0 1-.724.447l-1.052-.526a.5.5 0 0 0-.448 0l-1.052.526A.5.5 0 0 1 7 6.191V2zM5 0h6a4 4 0 0 1 4 4v8a4 4 0 0 1-4 4H5a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4z"/></symbol> - <symbol viewBox="0 0 16 16" id="branch" xmlns="http://www.w3.org/2000/svg"><path d="M6 11.978v.29a2 2 0 1 1-2 0V3.732a2 2 0 1 1 2 0v3.849c.592-.491 1.31-.854 2.15-1.081 1.308-.353 1.875-.882 1.893-1.743a2 2 0 1 1 2.002-.051C12.053 6.54 10.857 7.84 8.67 8.43 7.056 8.867 6.195 9.98 6 11.978zM5 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm6 1a1 1 0 1 0 0-2 1 1 0 0 0 0 2zM5 15a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol> - <symbol viewBox="0 0 16 16" id="calendar" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M12 2h2a2 2 0 0 1 2 2H0a2 2 0 0 1 2-2h2V1a1 1 0 1 1 2 0v1h4V1a1 1 0 1 1 2 0v1zM0 4h16v9a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V4zm2 2.5V13a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V6.5a.5.5 0 0 0-.5-.5h-11a.5.5 0 0 0-.5.5zM5 8h2a1 1 0 1 1 0 2H5a1 1 0 1 1 0-2z"/></symbol> - <symbol viewBox="0 0 16 16" id="cancel" xmlns="http://www.w3.org/2000/svg"><path d="M3.11 4.523a6 6 0 0 0 8.367 8.367L3.109 4.524zM4.522 3.11l8.368 8.368A6 6 0 0 0 4.524 3.11zM8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16z"/></symbol> - <symbol viewBox="0 0 16 16" id="chevron-down" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8.078 8.2l3.535-3.536a2 2 0 0 1 2.828 2.828l-4.949 4.95c-.39.39-.902.586-1.414.586a1.994 1.994 0 0 1-1.414-.586l-4.95-4.95a2 2 0 1 1 2.828-2.828l3.536 3.535z"/></symbol> - <symbol viewBox="0 0 16 16" id="chevron-left" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7.977 7.998l3.535-3.535a2 2 0 1 0-2.828-2.828l-4.95 4.949c-.39.39-.586.902-.586 1.414 0 .512.196 1.024.586 1.414l4.95 4.95a2 2 0 1 0 2.828-2.828L7.977 7.998z"/></symbol> - <symbol viewBox="0 0 16 16" id="chevron-right" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8.22 7.998L4.683 4.463a2 2 0 0 1 2.828-2.828l4.95 4.949c.39.39.586.902.586 1.414a1.99 1.99 0 0 1-.586 1.414l-4.95 4.95a2 2 0 0 1-2.828-2.828l3.535-3.536z"/></symbol> - <symbol viewBox="0 0 16 16" id="chevron-up" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7.778 8.957l3.535 3.535a2 2 0 1 0 2.828-2.828l-4.949-4.95a1.994 1.994 0 0 0-1.414-.586c-.512 0-1.024.196-1.414.586l-4.95 4.95a2 2 0 1 0 2.828 2.828l3.536-3.535z"/></symbol> - <symbol viewBox="0 0 16 16" id="clock" xmlns="http://www.w3.org/2000/svg"><path d="M9 7h1a1 1 0 0 1 0 2H8a.997.997 0 0 1-1-1V5a1 1 0 1 1 2 0v2zm-1 9A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12z"/></symbol> - <symbol viewBox="0 0 16 16" id="code" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M15.871 8.243a.997.997 0 0 0-.293-.707L12.75 4.707a1 1 0 0 0-1.414 1.414l2.12 2.122-2.12 2.121a1 1 0 0 0 1.414 1.414l2.828-2.828a.997.997 0 0 0 .293-.707zm-13.243 0L4.75 6.12a1 1 0 1 0-1.414-1.414L.507 7.536a.997.997 0 0 0 0 1.414l2.829 2.828a1 1 0 1 0 1.414-1.414L2.628 8.243zm6.407-4.107a1 1 0 0 1 .707 1.225L8.19 11.157a1 1 0 1 1-1.931-.518L7.81 4.843a1 1 0 0 1 1.224-.707z"/></symbol> - <symbol viewBox="0 0 16 16" id="comment" xmlns="http://www.w3.org/2000/svg"><path d="M1.707 15.707C1.077 16.337 0 15.891 0 15V3a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H5.414l-3.707 3.707zM2 12.586l2.293-2.293A1 1 0 0 1 5 10h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v9.586z"/></symbol> - <symbol viewBox="0 0 16 16" id="comment-dots" xmlns="http://www.w3.org/2000/svg"><path d="M1.707 15.707C1.077 16.337 0 15.891 0 15V3a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H5.414l-3.707 3.707zM2 12.586l2.293-2.293A1 1 0 0 1 5 10h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v9.586zM5 7a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol> - <symbol viewBox="0 0 16 16" id="comment-next" xmlns="http://www.w3.org/2000/svg"><path d="M8 5V4a.5.5 0 0 1 .8-.4l2.667 2a.5.5 0 0 1 0 .8L8.8 8.4A.5.5 0 0 1 8 8V7H6a1 1 0 1 1 0-2h2zM1.707 15.707C1.077 16.337 0 15.891 0 15V3a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H5.414l-3.707 3.707zM2 12.586l2.293-2.293A1 1 0 0 1 5 10h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v9.586z"/></symbol> - <symbol viewBox="0 0 16 16" id="comments" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M3.75 10L0 13V3a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2H3.75zM13 5h1a2 2 0 0 1 2 2v8l-2.667-2H8a2 2 0 0 1-2-2h4a3 3 0 0 0 3-3V5z"/></symbol> - <symbol viewBox="0 0 16 16" id="commit" xmlns="http://www.w3.org/2000/svg"><path d="M8 10a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm3.876-1.008a4.002 4.002 0 0 1-7.752 0A1.01 1.01 0 0 1 4 9H1a1 1 0 1 1 0-2h3c.042 0 .083.003.124.008a4.002 4.002 0 0 1 7.752 0A1.01 1.01 0 0 1 12 7h3a1 1 0 0 1 0 2h-3a1.01 1.01 0 0 1-.124-.008z"/></symbol> - <symbol viewBox="0 0 16 16" id="credit-card" xmlns="http://www.w3.org/2000/svg"><path d="M14 5a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1h12zm0 3H2v3a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V8zM3 2h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3zm6.5 8h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1z"/></symbol> - <symbol viewBox="0 0 16 16" id="disk" xmlns="http://www.w3.org/2000/svg"><path d="M16 11.764V3a3 3 0 0 0-3-3H3a3 3 0 0 0-3 3v8.764A2.989 2.989 0 0 1 2 11V3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v8c.768 0 1.47.289 2 .764zM2 12h12a2 2 0 1 1 0 4H2a2 2 0 1 1 0-4zm10 1a1 1 0 1 0 0 2 1 1 0 0 0 0-2z"/></symbol> - <symbol viewBox="0 0 16 16" id="doc_code" xmlns="http://www.w3.org/2000/svg"><path d="M8 2H5a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V7h-3a2 2 0 0 1-2-2V2zm2 .414V5h2.586L10 2.414zm1.036 7.607a.498.498 0 0 1-.147.354l-1.414 1.414a.5.5 0 0 1-.707-.707l1.06-1.06-1.06-1.061a.5.5 0 0 1 .707-.707l1.414 1.414a.498.498 0 0 1 .147.353zm-4.822 0l1.06 1.061a.5.5 0 0 1-.706.707l-1.414-1.414a.498.498 0 0 1 0-.707l1.414-1.414a.5.5 0 1 1 .707.707l-1.06 1.06zM5 0h4.586A2 2 0 0 1 11 .586L14.414 4A2 2 0 0 1 15 5.414V12a4 4 0 0 1-4 4H5a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4z"/></symbol> - <symbol viewBox="0 0 16 16" id="doc_image" xmlns="http://www.w3.org/2000/svg"><path d="M8 2H5a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V7h-3a2 2 0 0 1-2-2V2zm2 .414V5h2.586L10 2.414zM7.333 9.667l1.313-1.313a.5.5 0 0 1 .708 0L12 11H4l2.188-1.75a.5.5 0 0 1 .624 0l.521.417zM5 0h4.586A2 2 0 0 1 11 .586L14.414 4A2 2 0 0 1 15 5.414V12a4 4 0 0 1-4 4H5a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4zm.5 8a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zM4 11h8v.7a.3.3 0 0 1-.3.3H4.3a.3.3 0 0 1-.3-.3V11z"/></symbol> - <symbol viewBox="0 0 16 16" id="doc_text" xmlns="http://www.w3.org/2000/svg"><path d="M8 2H5a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V7h-3a2 2 0 0 1-2-2V2zm2 .414V5h2.586L10 2.414zM5 0h4.586A2 2 0 0 1 11 .586L14.414 4A2 2 0 0 1 15 5.414V12a4 4 0 0 1-4 4H5a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4zm.5 11h5a.5.5 0 1 1 0 1h-5a.5.5 0 1 1 0-1zm0-2h5a.5.5 0 1 1 0 1h-5a.5.5 0 0 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1z"/></symbol> - <symbol viewBox="0 0 16 16" id="download" xmlns="http://www.w3.org/2000/svg"><path d="M9 12h1a.5.5 0 0 1 .4.8l-2 2.667a.5.5 0 0 1-.8 0l-2-2.667A.5.5 0 0 1 6 12h1V8a1 1 0 1 1 2 0v4zM4 9a1 1 0 1 1 0 2 4 4 0 0 1-1.971-7.481 4 4 0 0 1 6.633-2.505 3.999 3.999 0 0 1 3.82 2.014A4 4 0 0 1 12 11a1 1 0 0 1 0-2 2 2 0 1 0 0-4h-1a2 2 0 0 0-3.112-1.662A2 2 0 1 0 4.268 5H4a2 2 0 1 0 0 4z"/></symbol> - <symbol viewBox="0 0 16 16" id="duplicate" xmlns="http://www.w3.org/2000/svg"><path d="M14 10h-3a1 1 0 0 1-1-1V6H8.527A.527.527 0 0 0 8 6.527V13a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1v-3zm-4-7H8.527c-.18 0-.355.013-.527.04V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2v2H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h4a3 3 0 0 1 3 3zM8.527 4h2.323a.5.5 0 0 1 .35.143l4.65 4.551a.5.5 0 0 1 .15.357V13a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V6.527A2.527 2.527 0 0 1 8.527 4z"/></symbol> - <symbol viewBox="0 0 16 16" id="earth" xmlns="http://www.w3.org/2000/svg"><path d="M8.7 2.04l-.082.177c.283.223.422.413.417.571-.008.237-.311.057-.444.274-.133.218.038.542-.112.637-.15.096-.398-.386-.479-.46-.054-.049-.166-.257-.336-.625l-.216-.225a.844.844 0 0 0-.418-.035c-.177.038-.075.1-.035.132.04.032.32.037.452.2.132.164.03.224-.05.298-.054.05-.157.062-.31.035H5.952l-.402.398.03.325.229.455.324-.463c.008-.206.058-.342.15-.41.14-.1.342-.15.534-.085.191.066-.057.218.011.271.068.053.204-.098.313-.02.11.08.07.155.104.322.036.167.254.114.398.328.144.215.19.29.147.483-.043.195-.168.26-.305.232-.138-.028-.107-.246-.275-.348-.168-.102-.266-.114-.386-.054-.12.06-.016.129.023.235.04.106.274.321.224.43-.05.107-.108.116-.42 0-.21-.077-.414-.007-.615.212l-.76.722c-.153.715-.3 1.13-.44 1.243-.211.17-.177-.483-.483-.656-.306-.174-.494-.047-.8-.07-.307-.023-.42.65-.38.873a.434.434 0 0 0 .221.321c.236-.141.39-.184.465-.128.11.084-.144.267-.074.425.07.158.314.069.386.283.073.213.084.48-.05.706-.135.227-.275.178-.4.053-.127-.126-.033-.375-.255-.704-.223-.329-.381-.337-.63-.787-.158-.287-.35-.743-.575-1.366a6 6 0 0 0 3.21 7.198l.001-.075c0-.577-.004-.944-.012-1.102-.011-.236-.95-.945-1.104-1.2-.154-.256-.34-.595-.355-.746-.016-.151.185-.232.344-.325.16-.093-.11-.367.028-.626.137-.258.395-.438.496-.356.101.081.058.228.267.333.209.104.077-.213.456-.178.38.035.143.201.252.216.11.016.113-.127.299-.143.186-.015.282.445.471.622.19.178.452.008.611.043.159.034.267.09.402.255.136.166-.03.352.073.557.103.205 1.07.22 1.433.255.364.034.371.011.371.324s-.166.314-.453.507c-.286.193-.166.462-.38.762-.212.3-.316.062-.622.14-.306.077-.413.382-.452.568-.039.186-.386.094-.877.232-.29.082-.429.144-.569.204a6.002 6.002 0 0 0 7.682-4.3c-.094-.384-.18-.63-.258-.74-.213-.297-.36.21-.924.49-.564.278-.57-.288-.81-.49-.16-.133-.212-.44-.158-.92-.005-.478.02-.828.077-1.049.057-.221.126-.543.207-.965.351-.373.606-.572.764-.595.237-.034.336.374.658.3a.315.315 0 0 0 .035-.01 5.993 5.993 0 0 0-.475-.824l-.309-.043a.646.646 0 0 0-.332-.117c-.205-.02-.025.128-.089.24-.064.112-.235.724-.437.685-.201-.039-.204-.374-.17-.668.036-.294-.077-.35-.2-.412-.124-.062-.325-.213-.556-.295-.232-.082-.123-.175-.093-.274.03-.1.208-.015.193-.058-.014-.044-.313-.135-.266-.167.03-.02.2-.02.506.003l.216-.012.293-.163a.58.58 0 0 0-.376-.22c-.233-.036-.513-.034-.73-.142-.205-.103-.458-.36-.643-.638A5.965 5.965 0 0 0 8.7 2.04zM8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16z"/></symbol> - <symbol viewBox="0 0 16 16" id="eye" xmlns="http://www.w3.org/2000/svg"><path d="M8 14C4.816 14 2.253 12.284.393 8.981a2 2 0 0 1 0-1.962C2.253 3.716 4.816 2 8 2s5.747 1.716 7.607 5.019a2 2 0 0 1 0 1.962C13.747 12.284 11.184 14 8 14zm0-2c2.41 0 4.338-1.29 5.864-4C12.338 5.29 10.411 4 8 4 5.59 4 3.662 5.29 2.136 8 3.662 10.71 5.589 12 8 12zm0-1a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm1-3a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol> - <symbol viewBox="0 0 16 16" id="eye-slash" xmlns="http://www.w3.org/2000/svg"><path d="M13.618 2.62L1.62 14.619a1 1 0 0 1-.985-1.668l1.525-1.526C1.516 10.742.926 9.927.393 8.981a2 2 0 0 1 0-1.962C2.253 3.716 4.816 2 8 2c1.074 0 2.076.195 3.006.58l.944-.944a1 1 0 0 1 1.668.985zM8.068 11a3 3 0 0 0 2.931-2.932l-2.931 2.931zm-3.02-2.462a3 3 0 0 1 3.49-3.49l.884-.884A6.044 6.044 0 0 0 8 4C5.59 4 3.662 5.29 2.136 8c.445.79.924 1.46 1.439 2.011l1.473-1.473zm.421 5.06l1.658-1.658c.283.04.575.06.873.06 2.41 0 4.338-1.29 5.864-4a11.023 11.023 0 0 0-1.133-1.664l1.418-1.418a12.799 12.799 0 0 1 1.458 2.1 2 2 0 0 1 0 1.963C13.747 12.284 11.184 14 8 14a7.883 7.883 0 0 1-2.53-.402z"/></symbol> - <symbol viewBox="0 0 16 16" id="file-additions" xmlns="http://www.w3.org/2000/svg"><path d="M7 7V5a1 1 0 1 1 2 0v2h2a1 1 0 0 1 0 2H9v2a1 1 0 0 1-2 0V9H5a1 1 0 1 1 0-2h2zM3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2H3z"/></symbol> - <symbol viewBox="0 0 16 16" id="file-deletion" xmlns="http://www.w3.org/2000/svg"><path d="M3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2H3zm2 6h6a1 1 0 0 1 0 2H5a1 1 0 1 1 0-2z"/></symbol> - <symbol viewBox="0 0 16 16" id="file-modified" xmlns="http://www.w3.org/2000/svg"><path d="M3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2H3zm5 4a3 3 0 1 1 0 6 3 3 0 0 1 0-6z"/></symbol> - <symbol viewBox="0 0 16 16" id="filter" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 6v9l-3.724-1.862A.5.5 0 0 1 6 12.691V6L1.854 1.854A.5.5 0 0 1 2.207 1h11.586a.5.5 0 0 1 .353.854L10 6z"/></symbol> - <symbol viewBox="0 0 16 16" id="folder" xmlns="http://www.w3.org/2000/svg"><path d="M7.228 5l-.475-1.335A1 1 0 0 0 5.81 3H2v9a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1H7.228zM13 3a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a2 2 0 0 1 2-2h3.81a3 3 0 0 1 2.827 1.995L13 3z"/></symbol> - <symbol viewBox="0 0 16 16" id="fork" xmlns="http://www.w3.org/2000/svg"><path d="M9 12.268a2 2 0 1 1-2 0V8.874A4.002 4.002 0 0 1 4 5V3.732a2 2 0 1 1 2 0V5a2 2 0 1 0 4 0V3.732a2 2 0 1 1 2 0V5a4.002 4.002 0 0 1-3 3.874v3.394zM11 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zM5 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 12a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol> - <symbol viewBox="0 0 16 16" id="git-merge" xmlns="http://www.w3.org/2000/svg"><path d="M11 12.268V5a1 1 0 0 0-1-1v1a.5.5 0 0 1-.8.4l-2.667-2a.5.5 0 0 1 0-.8L9.2.6a.5.5 0 0 1 .8.4v1a3 3 0 0 1 3 3v7.268a2 2 0 1 1-2 0zm-6 0a2 2 0 1 1-2 0V4.732a2 2 0 1 1 2 0v7.536zM4 4a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm0 11a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm8 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol> - <symbol viewBox="0 0 16 16" id="group" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M3.048 11.997C-.377 11.975.013 11.782.013 10.56.013 9.235.653 8 4 8c.444 0 .84.022 1.194.062.164.435.426.82.76 1.132-1.786.389-2.721 1.353-2.906 2.803zm2.94-7.222a2.993 2.993 0 0 0-.976 1.95 2 2 0 1 1 .975-1.95zm6.964 7.222c-.185-1.45-1.12-2.414-2.906-2.803.334-.311.596-.697.76-1.132C11.16 8.022 11.556 8 12 8c3.346 0 3.987 1.235 3.987 2.56 0 1.222.39 1.415-3.035 1.437zm-1.964-5.272a2.993 2.993 0 0 0-.976-1.95 2 2 0 1 1 .976 1.95zM8 9a2 2 0 1 1 0-4 2 2 0 0 1 0 4zm0 5c-2.177 0-3.987-.115-3.987-1.44S4.653 10 8 10c3.346 0 3.987 1.235 3.987 2.56S10.177 14 8 14z"/></symbol> - <symbol viewBox="0 0 16 16" id="history" xmlns="http://www.w3.org/2000/svg"><path d="M2.868 3.24a7 7 0 1 1-.043 9.475 1 1 0 0 1 1.478-1.348 5 5 0 1 0 .124-6.865l.796.645a.5.5 0 0 1-.193.873l-3.232.814a.5.5 0 0 1-.622-.504L1.3 3a.5.5 0 0 1 .814-.37l.754.61zM9 8h1a1 1 0 0 1 0 2H8a.997.997 0 0 1-1-1V6a1 1 0 1 1 2 0v2z"/></symbol> - <symbol viewBox="0 0 16 16" id="home" xmlns="http://www.w3.org/2000/svg"><path d="M8.462 2.177a.505.505 0 0 1-.038.044l.038-.044zm-.787 0l.038.043a.5.5 0 0 1-.038-.043zM3.706 7h8.725L8.069 2.585 3.706 7zM7 13.369V12a1 1 0 0 1 2 0v1.369h3V9H4v4.369h3zM14 9v4.836c0 .833-.657 1.533-1.5 1.533h-9c-.843 0-1.5-.7-1.5-1.533V9h-.448a1.1 1.1 0 0 1-.783-1.873L6.934.887a1.5 1.5 0 0 1 2.269 0l6.165 6.24A1.1 1.1 0 0 1 14.585 9H14z"/></symbol> - <symbol viewBox="0 0 16 16" id="hook" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 3a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1h4zm0 1H6v1a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1V4zM7 8a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h2a3 3 0 0 1 3 3v2a3 3 0 0 1-3 3v4a2 2 0 1 0 4 0h-.44a.3.3 0 0 1-.25-.466l1.44-2.16a.3.3 0 0 1 .5 0l1.44 2.16a.3.3 0 0 1-.25.466H15a4 4 0 0 1-7 2.646A4 4 0 0 1 1 12H.56a.3.3 0 0 1-.25-.466l1.44-2.16a.3.3 0 0 1 .5 0l1.44 2.16a.3.3 0 0 1-.25.466H3a2 2 0 1 0 4 0V8z"/></symbol> - <symbol viewBox="0 0 16 16" id="issue-block" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M5.803 8a5.97 5.97 0 0 0-.462 1H4.5a.5.5 0 0 1 0-1h1.303zM4.5 5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1 0-1zm7.5.083a6.04 6.04 0 0 0-2 0V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h2.083a5.96 5.96 0 0 0 .72 2H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h6a3 3 0 0 1 3 3v2.083zm1.121 3.796zM11 16a5 5 0 1 1 0-10 5 5 0 0 1 0 10zm-1.293-2.292a3 3 0 0 0 4.001-4.001l-4.001 4zm-1.415-1.415l4.001-4a3 3 0 0 0-4.001 4.001z"/></symbol> - <symbol viewBox="0 0 16 16" id="issue-child" xmlns="http://www.w3.org/2000/svg"><path d="M11 8H5v1h1a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1h2V7a.997.997 0 0 1 1-1h3V4H4.5a.5.5 0 0 1-.5-.5v-2a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.5.5H9v2h3a.997.997 0 0 1 1 1v2h2a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1h-5a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1h1V8zm-9 3v2h3v-2H2zm9 0v2h3v-2h-3z"/></symbol> - <symbol viewBox="0 0 16 16" id="issue-close" xmlns="http://www.w3.org/2000/svg"><path d="M7.536 8.657l2.828-2.829a1 1 0 0 1 1.414 1.415l-3.535 3.535a.997.997 0 0 1-1.415 0l-2.12-2.121A1 1 0 0 1 6.12 7.243l1.415 1.414zM8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12z"/></symbol> - <symbol viewBox="0 0 16 16" id="issue-duplicate" xmlns="http://www.w3.org/2000/svg"><path d="M10.874 2H12a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3h-2c-.918 0-1.74-.413-2.29-1.063a3.987 3.987 0 0 0 1.988-.984A1 1 0 0 0 10 14h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1h-1V3c0-.345-.044-.68-.126-1zM4 0h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H4z"/></symbol> - <symbol viewBox="0 0 16 16" id="issue-new" xmlns="http://www.w3.org/2000/svg"><path d="M10 2V1a1 1 0 0 1 2 0v1h1a1 1 0 0 1 0 2h-1v1a1 1 0 0 1-2 0V4H9a1 1 0 1 1 0-2h1zm0 6a1 1 0 0 1 2 0v5a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3h1a1 1 0 1 1 0 2H5a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1V8z"/></symbol> - <symbol viewBox="0 0 16 16" id="issue-open" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zm0-2a4 4 0 1 1 0-8 4 4 0 0 1 0 8zm0-2a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"/></symbol> - <symbol viewBox="0 0 16 16" id="issue-open-m" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12z"/></symbol> - <symbol viewBox="0 0 16 16" id="issue-parent" xmlns="http://www.w3.org/2000/svg"><path d="M11 11H5v1h1.5a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.5.5h-6a.5.5 0 0 1-.5-.5v-2a.5.5 0 0 1 .5-.5H3v-2a.997.997 0 0 1 1-1h3V7H5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1H9v2h3a.997.997 0 0 1 1 1v2h2.5a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.5.5h-6a.5.5 0 0 1-.5-.5v-2a.5.5 0 0 1 .5-.5H11v-1zM6 3v2h4V3H6z"/></symbol> - <symbol viewBox="0 0 16 16" id="issues" xmlns="http://www.w3.org/2000/svg"><path d="M10.458 15.012l.311.055a3 3 0 0 0 3.476-2.433l1.389-7.879A3 3 0 0 0 13.2 1.28L11.23.933a3.002 3.002 0 0 0-.824-.031c.364.59.58 1.28.593 2.02l1.854.328a1 1 0 0 1 .811 1.158l-1.389 7.879a1 1 0 0 1-1.158.81l-.118-.02a3.98 3.98 0 0 1-.541 1.935zM3 0h4a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3z"/></symbol> - <symbol viewBox="0 0 16 16" id="key" xmlns="http://www.w3.org/2000/svg"><path d="M7.575 6.689a4.002 4.002 0 0 1 6.274-4.86 4 4 0 0 1-4.86 6.274l-2.21 2.21.706.708a1 1 0 1 1-1.414 1.414l-.707-.707-.707.707.707.707a1 1 0 1 1-1.414 1.414l-.707-.707a1 1 0 0 1-1.414-1.414l5.746-5.746zm2.032-.618a2 2 0 1 0 2.828-2.828A2 2 0 0 0 9.607 6.07z"/></symbol> - <symbol viewBox="0 0 16 16" id="key-2" xmlns="http://www.w3.org/2000/svg"><path d="M5.172 14.157l-.344.344-2.485.133a.462.462 0 0 1-.497-.503l.14-2.24a.599.599 0 0 1 .177-.382l5.155-5.155a4 4 0 1 1 2.828 2.828l-1.439 1.44-1.06-.354-.708.707.354 1.06-.707.708-1.06-.354-.708.707.354 1.06zm6.01-8.839a1 1 0 1 0 1.414-1.414 1 1 0 0 0-1.414 1.414z"/></symbol> - <symbol viewBox="0 0 16 16" id="label" xmlns="http://www.w3.org/2000/svg"><path d="M11.782 14.718a3 3 0 0 1-4.242 0L1.652 8.829a2 2 0 0 1-.565-1.702l.54-3.703a2 2 0 0 1 1.69-1.69l3.703-.54a2 2 0 0 1 1.703.564l5.888 5.888a3 3 0 0 1 0 4.243l-2.829 2.829zm1.415-5.657L7.309 3.173l-3.703.54-.54 3.702 5.888 5.888a1 1 0 0 0 1.414 0l2.829-2.828a1 1 0 0 0 0-1.414zM5.732 5.525A1 1 0 1 1 7.146 6.94a1 1 0 0 1-1.414-1.414z"/></symbol> - <symbol viewBox="0 0 16 16" id="labels" xmlns="http://www.w3.org/2000/svg"><path d="M9.424 2.254l2.08-.905a1 1 0 0 1 1.206.326l3.013 4.12a1 1 0 0 1 .16.849l-1.947 7.264a3 3 0 0 1-3.675 2.122l-.5-.135a3.999 3.999 0 0 0 1.082-1.782 1 1 0 0 0 1.16-.722l1.823-6.802-2.258-3.087-.687.299a2 2 0 0 0-.628-.88l-.829-.667zM.377 3.7L4.4.498a1 1 0 0 1 1.25.003L9.627 3.7a1 1 0 0 1 .373.78V13a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V4.482A1 1 0 0 1 .377 3.7zM2 13a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1V4.958L5.02 2.561 2 4.964V13zm3-6a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol> - <symbol viewBox="0 0 16 16" id="leave" xmlns="http://www.w3.org/2000/svg"><path d="M11 7V5.883a.5.5 0 0 1 .757-.429l3.528 2.117a.5.5 0 0 1 0 .858l-3.528 2.117a.5.5 0 0 1-.757-.43V9H7a1 1 0 1 1 0-2h4zm-2 6.256a1 1 0 0 1 2 0A2.744 2.744 0 0 1 8.256 16H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h5.19A2.81 2.81 0 0 1 11 2.81a1 1 0 0 1-2 0A.81.81 0 0 0 8.19 2H3a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h5.256c.41 0 .744-.333.744-.744z"/></symbol> - <symbol viewBox="0 0 16 16" id="level-up" xmlns="http://www.w3.org/2000/svg"><path fill="#2E2E2E" fill-rule="evenodd" d="M7 6h3.489a.5.5 0 0 0 .373-.832L6.374.117a.5.5 0 0 0-.748 0l-4.488 5.05A.5.5 0 0 0 1.51 6H5v7a3 3 0 0 0 3 3h6a1 1 0 0 0 0-2H8a1 1 0 0 1-1-1V6z"/></symbol> - <symbol viewBox="0 0 16 16" id="license" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M12.56 8.9l2.66 4.606a.3.3 0 0 1-.243.45l-1.678.094a.1.1 0 0 0-.078.044l-.953 1.432a.3.3 0 0 1-.51-.016L9.097 10.9a5.994 5.994 0 0 0 3.464-2zm-5.23 2.063L4.707 15.51a.3.3 0 0 1-.51.016l-.953-1.432a.1.1 0 0 0-.078-.044l-1.678-.094a.3.3 0 0 1-.243-.45l2.48-4.297a5.983 5.983 0 0 0 3.607 1.754zM8 10A5 5 0 1 1 8 0a5 5 0 0 1 0 10zm0-2a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-1a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"/></symbol> - <symbol viewBox="0 0 16 16" id="link" xmlns="http://www.w3.org/2000/svg"><path d="M6.986 3.35l2.12-2.122a4 4 0 0 1 5.657 5.657l-2.828 2.829a4 4 0 0 1-5.657 0 1 1 0 0 1 1.414-1.415 2 2 0 0 0 2.829 0l2.828-2.828a2 2 0 1 0-2.828-2.828l-1.001 1a5.018 5.018 0 0 0-2.534-.294zm2.12 9.192l-2.12 2.121a4 4 0 1 1-5.658-5.656l2.829-2.829a4 4 0 0 1 5.657 0 1 1 0 1 1-1.415 1.414 2 2 0 0 0-2.828 0l-2.828 2.829a2 2 0 1 0 2.828 2.828l1.001-1.001a5.018 5.018 0 0 0 2.534.294z"/></symbol> - <symbol viewBox="0 0 16 16" id="list-bulleted" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M1 4a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm0 5a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4-7h10a1 1 0 0 1 0 2H5a1 1 0 1 1 0-2zm0 5h10a1 1 0 0 1 0 2H5a1 1 0 1 1 0-2zm-4 7a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4-2h10a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2z"/></symbol> - <symbol viewBox="0 0 16 16" id="list-numbered" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M6 2h8a1 1 0 0 1 0 2H6a1 1 0 1 1 0-2zm0 5h8a1 1 0 0 1 0 2H6a1 1 0 1 1 0-2zm0 5h8a1 1 0 0 1 0 2H6a1 1 0 0 1 0-2zM1.156 5v-.828h.816V2.204h-.72v-.636c.432-.084.708-.192.996-.372h.756v2.976h.684V5H1.156zm-.18 5v-.588c.9-.828 1.596-1.464 1.596-1.98 0-.342-.192-.504-.468-.504-.252 0-.444.18-.624.36l-.552-.552c.396-.42.756-.612 1.32-.612.768 0 1.308.492 1.308 1.248 0 .612-.576 1.284-1.092 1.812.192-.024.468-.048.636-.048h.636V10H.976zm1.26 5.072c-.618 0-1.068-.204-1.356-.54l.468-.648c.234.216.51.36.78.36.336 0 .552-.12.552-.36 0-.288-.15-.456-.948-.456v-.72c.636 0 .828-.168.828-.432 0-.228-.138-.348-.396-.348-.252 0-.432.108-.672.312l-.516-.624c.372-.312.768-.492 1.236-.492.84 0 1.38.384 1.38 1.074 0 .366-.204.642-.612.822v.024c.432.132.732.432.732.912 0 .72-.684 1.116-1.476 1.116z"/></symbol> - <symbol viewBox="0 0 16 16" id="location" xmlns="http://www.w3.org/2000/svg"><path d="M8.755 15.144a1 1 0 0 1-1.51 0C3.748 11.114 2 8.065 2 6a6 6 0 1 1 12 0c0 2.065-1.748 5.113-5.245 9.144zM12 6a4 4 0 1 0-8 0c0 1.314 1.312 3.71 4 6.944C10.688 9.71 12 7.314 12 6zM8 8a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"/></symbol> - <symbol viewBox="0 0 16 16" id="location-dot" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M6.314 13.087C4.382 13.295 3 13.85 3 14.5c0 .828 2.239 1.5 5 1.5s5-.672 5-1.5c0-.65-1.382-1.205-3.314-1.413l-.202.225a2 2 0 0 1-2.968 0l-.202-.225zm2.428-.445a1 1 0 0 1-1.484 0C4.419 9.5 3 7.037 3 5.252 3 2.353 5.239 0 8 0s5 2.352 5 5.253c0 1.784-1.42 4.247-4.258 7.389zM11 5.252C11 3.436 9.634 2 8 2S5 3.435 5 5.253c0 1.027.974 2.824 3 5.203 2.026-2.38 3-4.176 3-5.203zM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol> - <symbol viewBox="0 0 16 16" id="lock" xmlns="http://www.w3.org/2000/svg"><path d="M10 5V4h2v1a3 3 0 0 1 3 3v5a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V8a3 3 0 0 1 3-3V4h2v1h4zM4 7a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V8a1 1 0 0 0-1-1H4zm0-3a4 4 0 1 1 8 0h-2a2 2 0 1 0-4 0H4z"/></symbol> - <symbol viewBox="0 0 16 16" id="lock-open" xmlns="http://www.w3.org/2000/svg"><path d="M4.044 4a4 4 0 0 1 6.99-2.658 1 1 0 1 1-1.495 1.33A2 2 0 0 0 6.044 4a.998.998 0 0 1-.07.367v.701H12a3 3 0 0 1 3 3v5a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3v-5a3 3 0 0 1 2.974-3V4h.07zM4 7.07a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-5a1 1 0 0 0-1-1H4z"/></symbol> - <symbol viewBox="0 0 16 16" id="log" xmlns="http://www.w3.org/2000/svg"><path d="M4 0h8a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H4zm1 4a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm0 3a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3-5h3a1 1 0 0 1 0 2H8a1 1 0 1 1 0-2zm0 3h3a1 1 0 0 1 0 2H8a1 1 0 1 1 0-2zm-3 5a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3-2h3a1 1 0 0 1 0 2H8a1 1 0 0 1 0-2z"/></symbol> - <symbol viewBox="0 0 16 16" id="mail" xmlns="http://www.w3.org/2000/svg"><path d="M14 5.6L9.338 9.796a2 2 0 0 1-2.676 0L2 5.6V11a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V5.6zM3 2h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3zm.212 2L8 8.31 12.788 4H3.212z"/></symbol> - <symbol viewBox="0 0 16 16" id="merge-request-close" xmlns="http://www.w3.org/2000/svg"><path d="M9.414 8l1.414 1.414a1 1 0 1 1-1.414 1.414L8 9.414l-1.414 1.414a1 1 0 1 1-1.414-1.414L6.586 8 5.172 6.586a1 1 0 1 1 1.414-1.414L8 6.586l1.414-1.414a1 1 0 1 1 1.414 1.414L9.414 8zM8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12z"/></symbol> - <symbol viewBox="0 0 16 16" id="merge-request-close-m" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M9.414 8l4.95-4.95a1 1 0 0 0-1.414-1.414L8 6.586l-4.95-4.95A1 1 0 0 0 1.636 3.05L6.586 8l-4.95 4.95a1 1 0 1 0 1.414 1.414L8 9.414l4.95 4.95a1 1 0 1 0 1.414-1.414L9.414 8z"/></symbol> - <symbol viewBox="0 0 16 16" id="messages" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8.588 8.942l1.173 5.862A1 1 0 0 1 8.78 16H7.22a1 1 0 0 1-.98-1.196l1.172-5.862a3.014 3.014 0 0 0 1.176 0zM8 8a2 2 0 1 1 0-4 2 2 0 0 1 0 4zM4.464 2.464L5.88 3.88a3 3 0 0 0 0 4.242L4.464 9.536a5 5 0 0 1 0-7.072zm7.072 7.072L10.12 8.12a3 3 0 0 0 0-4.242l1.415-1.415a5 5 0 0 1 0 7.072zM2.343.343l1.414 1.414a6 6 0 0 0 0 8.486l-1.414 1.414a8 8 0 0 1 0-11.314zm11.314 11.314l-1.414-1.414a6 6 0 0 0 0-8.486L13.657.343a8 8 0 0 1 0 11.314z"/></symbol> - <symbol viewBox="0 0 16 16" id="mobile-issue-close" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M5.657 10.728L2.12 7.192A1 1 0 1 0 .707 8.607l4.243 4.242a.997.997 0 0 0 1.414 0l8.485-8.485a1 1 0 1 0-1.414-1.414l-7.778 7.778z"/></symbol> - <symbol viewBox="0 0 16 16" id="monitor" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 13v1h3a1 1 0 0 1 0 2H3a1 1 0 0 1 0-2h3v-1H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v7a3 3 0 0 1-3 3h-3zM3 2a1 1 0 0 0-1 1v7a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3zm5.723 6.416l-2.66-1.773-1.71 1.71a.5.5 0 1 1-.707-.707l2-2a.5.5 0 0 1 .631-.062l2.66 1.773 2.71-2.71a.5.5 0 0 1 .707.707l-3 3a.5.5 0 0 1-.631.062z"/></symbol> - <symbol viewBox="0 0 16 16" id="more" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8 4a2 2 0 1 1 0-4 2 2 0 0 1 0 4zm0 6a2 2 0 1 1 0-4 2 2 0 0 1 0 4zm0 6a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"/></symbol> - <symbol viewBox="0 0 16 16" id="notifications" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M6 14H2.435a2 2 0 0 1-1.761-2.947c.962-1.788 1.521-3.065 1.68-3.832.322-1.566.947-5.501 4.65-6.134a1 1 0 1 1 1.994-.024c3.755.528 4.375 4.27 4.761 6.043.188.86.742 2.188 1.661 3.982A2 2 0 0 1 13.64 14H10a2 2 0 1 1-4 0zm5.805-6.468c-.325-1.492-.37-1.674-.61-2.288C10.6 3.716 9.742 3 8.07 3c-1.608 0-2.49.718-3.103 2.197-.28.676-.356.982-.654 2.428-.208 1.012-.827 2.424-1.877 4.375H13.64c-.993-1.937-1.6-3.396-1.835-4.468z"/></symbol> - <symbol viewBox="0 0 16 16" id="notifications-off" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M13.26 5.089c.243.757.382 1.478.5 2.017.187.86.74 2.188 1.66 3.982A2 2 0 0 1 13.64 14H10a2 2 0 1 1-4 0H4.35l2-2h7.29c-.993-1.937-1.6-3.396-1.835-4.468-.07-.326-.129-.59-.178-.81l1.634-1.633zM10.943 1.75l-1.48 1.48C9.07 3.076 8.612 3 8.069 3c-1.608 0-2.49.718-3.103 2.197-.28.676-.356.982-.654 2.428-.065.317-.17.673-.317 1.073L.45 12.242a1.99 1.99 0 0 1 .224-1.19c.962-1.787 1.521-3.064 1.68-3.831.322-1.566.947-5.501 4.65-6.134a1 1 0 1 1 1.994-.024 4.867 4.867 0 0 1 1.944.688zm2.932-.105a1 1 0 0 1 0 1.415L2.561 14.374a1 1 0 1 1-1.415-1.414L12.46 1.646a1 1 0 0 1 1.414 0z"/></symbol> - <symbol viewBox="0 0 16 16" id="overview" xmlns="http://www.w3.org/2000/svg"><path d="M2 0h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2zm0 2v3h3V2H2zm9-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2h-3a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2zm0 2v3h3V2h-3zM2 9h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2zm0 2v3h3v-3H2zm9-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2h-3a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2zm0 2v3h3v-3h-3z"/></symbol> - <symbol viewBox="0 0 16 16" id="pencil" xmlns="http://www.w3.org/2000/svg"><path d="M13.02 1.293l1.414 1.414a1 1 0 0 1 0 1.414L4.119 14.436a1 1 0 0 1-.704.293l-2.407.008L1 12.316a1 1 0 0 1 .293-.71L11.605 1.292a1 1 0 0 1 1.414 0zm-1.416 1.415l-.707.707L12.31 4.83l.707-.707-1.414-1.415zM3.411 13.73l1.123-1.122H3.12v-1.415L2 12.312l.005 1.422 1.406-.005z"/></symbol> - <symbol viewBox="0 0 16 16" id="pipeline" xmlns="http://www.w3.org/2000/svg"><path d="M8.969 7.25a2 2 0 1 1-1.938 0A1.002 1.002 0 0 1 7 7V5.083a.2.2 0 0 1 .06-.142l.877-.87a.1.1 0 0 1 .141 0l.864.87A.2.2 0 0 1 9 5.083V7c0 .086-.01.17-.031.25zM8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zm4.5-4a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm0-3a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm-2 6a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm0-9a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm-5 9a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm0-9a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm-2 6a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm0-3a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zM8 10a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol> - <symbol viewBox="0 0 16 16" id="play" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M2.765 15.835c-.545.321-1.258.159-1.593-.363A1.075 1.075 0 0 1 1 14.89V1.11C1 .496 1.518 0 2.158 0c.214 0 .424.057.607.165l11.684 6.89c.544.321.714 1.005.38 1.526a1.135 1.135 0 0 1-.38.364l-11.684 6.89z"/></symbol> - <symbol viewBox="0 0 16 16" id="plus" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7 7V1a1 1 0 1 1 2 0v6h6a1 1 0 0 1 0 2H9v6a1 1 0 0 1-2 0V9H1a1 1 0 1 1 0-2h6z"/></symbol> - <symbol viewBox="0 0 16 16" id="plus-square" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M9 7V4a1 1 0 1 0-2 0v3H4a1 1 0 1 0 0 2h3v3a1 1 0 0 0 2 0V9h3a1 1 0 0 0 0-2H9zM3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3z"/></symbol> - <symbol viewBox="0 0 16 16" id="plus-square-o" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7 7V5a1 1 0 1 1 2 0v2h2a1 1 0 0 1 0 2H9v2a1 1 0 0 1-2 0V9H5a1 1 0 1 1 0-2h2zM3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3z"/></symbol> - <symbol viewBox="0 0 16 16" id="preferences" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M5 12h10a1 1 0 0 1 0 2H5a1 1 0 0 1-2 0v-2a1 1 0 0 1 2 0zm-3 0H1a1 1 0 0 0 0 2h1v-2zm11-5h2a1 1 0 0 1 0 2h-2a1 1 0 0 1-2 0V7a1 1 0 0 1 2 0zm-3 0H1a1 1 0 1 0 0 2h9V7zM6 2h9a1 1 0 0 1 0 2H6a1 1 0 1 1-2 0V2a1 1 0 1 1 2 0zM3 2H1a1 1 0 1 0 0 2h2V2z"/></symbol> - <symbol viewBox="0 0 16 16" id="profile" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zm-4.274-3.404C4.412 9.709 5.694 9 8 9c2.313 0 3.595.7 4.28 1.586A4.997 4.997 0 0 1 8 13a4.997 4.997 0 0 1-4.274-2.404zM8 8a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"/></symbol> - <symbol viewBox="0 0 16 16" id="project" xmlns="http://www.w3.org/2000/svg"><path d="M8.462 2.177l-.038.044a.505.505 0 0 0 .038-.044zm-.787 0a.5.5 0 0 0 .038.043l-.038-.043zM3.706 7h8.725L8.069 2.585 3.706 7zM7 13.369V12a1 1 0 0 1 2 0v1.369h3V9H4v4.369h3zM14 9v4.836c0 .833-.657 1.533-1.5 1.533h-9c-.843 0-1.5-.7-1.5-1.533V9h-.448a1.1 1.1 0 0 1-.783-1.873L6.934.887a1.5 1.5 0 0 1 2.269 0l6.165 6.24A1.1 1.1 0 0 1 14.585 9H14z"/></symbol> - <symbol viewBox="0 0 16 16" id="push-rules" xmlns="http://www.w3.org/2000/svg"><path d="M6.268 9a2 2 0 0 1 3.464 0H11a1 1 0 0 1 0 2H9.732a2 2 0 0 1-3.464 0H5a1 1 0 0 1 0-2h1.268zM7 2H4a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1h-1v3.515a.3.3 0 0 1-.434.268l-1.432-.716a.3.3 0 0 0-.268 0l-1.432.716A.3.3 0 0 1 7 5.515V2zM4 0h8a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm4 11a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></symbol> - <symbol viewBox="0 0 16 16" id="question" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm-1.46-5.602h2.233a3.97 3.97 0 0 1 .051-.558c.029-.17.073-.326.133-.469.06-.143.14-.28.242-.41.102-.13.228-.263.38-.399.26-.24.504-.467.733-.683a5.03 5.03 0 0 0 .598-.668c.17-.23.302-.477.399-.742a2.66 2.66 0 0 0 .144-.907c0-.505-.083-.95-.25-1.335a2.55 2.55 0 0 0-.723-.97 3.2 3.2 0 0 0-1.152-.589 5.441 5.441 0 0 0-1.531-.2c-.516 0-.998.063-1.445.188a3.19 3.19 0 0 0-1.168.59c-.331.268-.594.61-.79 1.027-.195.417-.295.917-.3 1.5h2.64c.006-.224.04-.416.102-.578.062-.161.142-.293.238-.394a.921.921 0 0 1 .332-.227 1.04 1.04 0 0 1 .39-.074c.34 0 .593.095.763.285.169.19.254.488.254.895 0 .328-.106.63-.317.906-.21.276-.499.565-.863.867-.214.182-.39.374-.531.574-.141.2-.253.42-.336.657a3.656 3.656 0 0 0-.176.777 7.89 7.89 0 0 0-.05.937zm-.321 2.375c0 .188.035.362.105.524.07.161.17.3.301.418.13.117.284.21.46.277.178.068.376.102.595.102.218 0 .416-.034.593-.102.178-.068.331-.16.461-.277a1.2 1.2 0 0 0 .301-.418c.07-.162.106-.336.106-.524a1.3 1.3 0 0 0-.106-.523 1.2 1.2 0 0 0-.3-.418 1.461 1.461 0 0 0-.462-.277 1.651 1.651 0 0 0-.593-.102c-.22 0-.417.034-.594.102a1.46 1.46 0 0 0-.461.277 1.2 1.2 0 0 0-.3.418 1.284 1.284 0 0 0-.106.523z"/></symbol> - <symbol viewBox="0 0 16 16" id="question-o" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zm-.778-4.151c0-.301.014-.575.044-.82a3.2 3.2 0 0 1 .154-.68c.073-.208.17-.4.294-.575.123-.176.278-.343.465-.503a4.81 4.81 0 0 0 .755-.758c.185-.242.277-.506.277-.793 0-.356-.074-.617-.222-.783-.148-.166-.37-.25-.667-.25a.92.92 0 0 0-.342.065.806.806 0 0 0-.29.199 1.04 1.04 0 0 0-.209.345 1.5 1.5 0 0 0-.088.506H5.082c.005-.51.092-.948.263-1.313.171-.364.401-.664.69-.899.29-.234.63-.406 1.023-.516a4.66 4.66 0 0 1 1.264-.164c.497 0 .944.058 1.34.174.397.117.733.289 1.008.517.276.227.487.51.633.847.146.337.218.727.218 1.17 0 .295-.042.56-.126.792a2.52 2.52 0 0 1-.349.65 4.4 4.4 0 0 1-.523.584c-.2.19-.414.389-.642.598a2.73 2.73 0 0 0-.332.349c-.089.114-.16.233-.212.359a1.868 1.868 0 0 0-.116.41 3.39 3.39 0 0 0-.044.489H7.222zm-.28 2.078c0-.164.03-.317.092-.458a1.05 1.05 0 0 1 .263-.366c.114-.103.248-.183.403-.243a1.45 1.45 0 0 1 .52-.089c.191 0 .364.03.52.09.154.059.289.14.403.242.114.103.201.224.263.366.061.141.092.294.092.458 0 .164-.03.316-.092.458a1.05 1.05 0 0 1-.263.365 1.278 1.278 0 0 1-.404.243 1.43 1.43 0 0 1-.52.089c-.19 0-.364-.03-.519-.089-.155-.06-.29-.14-.403-.243a1.05 1.05 0 0 1-.263-.365 1.135 1.135 0 0 1-.093-.458z"/></symbol> - <symbol viewBox="0 0 16 16" id="quote" xmlns="http://www.w3.org/2000/svg"><path d="M15 3v8a3 3 0 0 1-3 3 1 1 0 0 1 0-2 1 1 0 0 0 1-1V9h-2a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h3a1 1 0 0 1 1 1zM7 3v8a3 3 0 0 1-3 3 1 1 0 0 1 0-2 1 1 0 0 0 1-1V9H3a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h3a1 1 0 0 1 1 1z"/></symbol> - <symbol viewBox="0 0 16 16" id="redo" xmlns="http://www.w3.org/2000/svg"><path d="M4.666 4.423a5 5 0 1 1-.203 6.944 1 1 0 1 0-1.478 1.347 7 7 0 1 0 .12-9.556L1.842 2.137a.5.5 0 0 0-.815.385L1 7.26a.5.5 0 0 0 .607.492l4.629-1.013a.5.5 0 0 0 .207-.877L4.666 4.423z"/></symbol> - <symbol viewBox="0 0 16 16" id="remove" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M2 3a1 1 0 1 1 0-2h12a1 1 0 0 1 0 2v10a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V3zm3-2a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1H5zM4 3v10a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V3H4zm2.5 2a.5.5 0 0 1 .5.5v6a.5.5 0 1 1-1 0v-6a.5.5 0 0 1 .5-.5zm3 0a.5.5 0 0 1 .5.5v6a.5.5 0 1 1-1 0v-6a.5.5 0 0 1 .5-.5z"/></symbol> - <symbol viewBox="0 0 16 16" id="repeat" xmlns="http://www.w3.org/2000/svg"><path d="M11.494 4.423a5 5 0 1 0 .203 6.944 1 1 0 1 1 1.478 1.347 7 7 0 1 1-.12-9.556l1.262-1.021a.5.5 0 0 1 .815.385l.028 4.738a.5.5 0 0 1-.607.492L9.924 6.739a.5.5 0 0 1-.207-.877l1.777-1.439z"/></symbol> - <symbol viewBox="0 0 16 16" id="retry" xmlns="http://www.w3.org/2000/svg"><path d="M4.009 6.958a4 4 0 0 0 5.283 4.775 1 1 0 0 1 .712 1.87A6 6 0 0 1 2.077 6.44l-.741-.2a.5.5 0 0 1-.12-.915L3.41 4.058a.5.5 0 0 1 .683.183l1.268 2.196a.5.5 0 0 1-.563.733l-.79-.212zm7.777 2.084a4 4 0 0 0-5.284-4.775 1 1 0 0 1-.711-1.87 6 6 0 0 1 7.927 7.162l.74.2a.5.5 0 0 1 .121.915l-2.196 1.268a.5.5 0 0 1-.683-.183l-1.267-2.196a.5.5 0 0 1 .562-.733l.79.212z"/></symbol> - <symbol viewBox="0 0 16 16" id="scale" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M13.99 9a.792.792 0 0 0-.078-.231L13 7l-.912 1.769a.791.791 0 0 0-.077.231h1.978zm-10 0a.792.792 0 0 0-.078-.231L3 7l-.912 1.769A.791.791 0 0 0 2.011 9h1.978zM2 0h12a1 1 0 0 1 0 2H2a1 1 0 1 1 0-2zm3 14h6a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2zM8 4a1 1 0 0 1 1 1v9H7V5a1 1 0 0 1 1-1zm-4.53-.714l2.265 4.735c.68 1.42.006 3.091-1.504 3.73A3.161 3.161 0 0 1 3 12c-1.657 0-3-1.263-3-2.821 0-.4.09-.794.264-1.158L2.53 3.286a.53.53 0 0 1 .94 0zm10 0l2.265 4.735c.68 1.42.006 3.091-1.504 3.73A3.161 3.161 0 0 1 13 12c-1.657 0-3-1.263-3-2.821 0-.4.09-.794.264-1.158l2.266-4.735a.53.53 0 0 1 .94 0z"/></symbol> - <symbol viewBox="0 0 16 16" id="screen-full" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M14 14v-2a1 1 0 0 1 2 0v3a.997.997 0 0 1-1 1h-3a1 1 0 0 1 0-2h2zM2 14v-2a1 1 0 0 0-2 0v3a1 1 0 0 0 1 1h3a1 1 0 0 0 0-2H2zM15.707.293A.997.997 0 0 1 16 1v3a1 1 0 0 1-2 0V2h-2a1 1 0 0 1 0-2h3c.276 0 .526.112.707.293zM2 2v2a1 1 0 1 1-2 0V1a.997.997 0 0 1 1-1h3a1 1 0 1 1 0 2H2zm4 4h4a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1z"/></symbol> - <symbol viewBox="0 0 16 16" id="screen-normal" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M3 3V1a1 1 0 1 1 2 0v3a.997.997 0 0 1-1 1H1a1 1 0 1 1 0-2h2zm10 0h2a1 1 0 0 1 0 2h-3a.997.997 0 0 1-1-1V1a1 1 0 0 1 2 0v2zM3 13H1a1 1 0 0 1 0-2h3a.997.997 0 0 1 1 1v3a1 1 0 0 1-2 0v-2zm10 0v2a1 1 0 0 1-2 0v-3a.997.997 0 0 1 1-1h3a1 1 0 0 1 0 2h-2zM6.5 7h3a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5z"/></symbol> - <symbol viewBox="0 0 16 16" id="search" xmlns="http://www.w3.org/2000/svg"><path d="M8.853 8.854a3.5 3.5 0 1 0-4.95-4.95 3.5 3.5 0 0 0 4.95 4.95zm.207 2.328a5.5 5.5 0 1 1 2.121-2.121l3.329 3.328a1.5 1.5 0 0 1-2.121 2.121L9.06 11.182z"/></symbol> - <symbol viewBox="0 0 16 16" id="settings" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M2.415 5.803L1.317 4.084A.5.5 0 0 1 1.35 3.5l.805-.994a.5.5 0 0 1 .564-.153l1.878.704a5.975 5.975 0 0 1 1.65-.797L6.885.342A.5.5 0 0 1 7.36 0h1.28a.5.5 0 0 1 .474.342l.639 1.918a5.97 5.97 0 0 1 1.65.797l1.877-.704a.5.5 0 0 1 .565.153l.805.994a.5.5 0 0 1 .032.584l-1.097 1.719c.217.551.354 1.143.399 1.76l1.731 1.058a.5.5 0 0 1 .227.54l-.288 1.246a.5.5 0 0 1-.44.385l-2.008.19a6.026 6.026 0 0 1-1.142 1.431l.265 1.995a.5.5 0 0 1-.277.516l-1.15.56a.5.5 0 0 1-.576-.1l-1.424-1.452a6.047 6.047 0 0 1-1.804 0l-1.425 1.453a.5.5 0 0 1-.576.1l-1.15-.561a.5.5 0 0 1-.276-.516l.265-1.995a6.026 6.026 0 0 1-1.143-1.43l-2.008-.191a.5.5 0 0 1-.44-.385L.058 9.16a.5.5 0 0 1 .226-.539l1.732-1.058a5.968 5.968 0 0 1 .399-1.76zM8 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/></symbol> - <symbol viewBox="0 0 16 16" id="shield" xmlns="http://www.w3.org/2000/svg"><path d="M4 0h8a3 3 0 0 1 3 3v7.186a3 3 0 0 1-1.426 2.554l-4 2.465a3 3 0 0 1-3.148 0l-4-2.465A3 3 0 0 1 1 10.186V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v7.186a1 1 0 0 0 .475.852l4 2.464a1 1 0 0 0 1.05 0l4-2.464a1 1 0 0 0 .475-.852V3a1 1 0 0 0-1-1H4zm0 1.5a.5.5 0 0 1 .5-.5h4v8.837a.5.5 0 0 1-.753.431l-3.5-2.052A.5.5 0 0 1 4 9.785V3.5z"/></symbol> - <symbol viewBox="0 0 16 16" id="slight-frown" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zm-2.163-3.275a2.499 2.499 0 0 1 4.343.03.5.5 0 0 1-.871.49 1.5 1.5 0 0 0-2.607-.018.5.5 0 1 1-.865-.502zM5 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm6 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol> - <symbol viewBox="0 0 16 16" id="slight-smile" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zM5 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm6 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm-5.163 2.254a.5.5 0 1 1 .865-.502 1.499 1.499 0 0 0 2.607-.018.5.5 0 1 1 .871.49 2.499 2.499 0 0 1-4.343.03z"/></symbol> - <symbol viewBox="0 0 16 16" id="smile" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zM6.18 6.27a.5.5 0 0 1-.873.487.5.5 0 0 0-.872-.003.5.5 0 1 1-.87-.495 1.5 1.5 0 0 1 2.616.012zm6 0a.5.5 0 1 1-.873.487.5.5 0 0 0-.872-.003.5.5 0 1 1-.87-.495 1.5 1.5 0 0 1 2.616.012zM5 9a3 3 0 0 0 6 0H5z"/></symbol> - <symbol viewBox="0 0 16 16" id="smiley" xmlns="http://www.w3.org/2000/svg"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zM5 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm6 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zM5 9h6a3 3 0 0 1-6 0z"/></symbol> - <symbol viewBox="0 0 16 16" id="snippet" xmlns="http://www.w3.org/2000/svg"><path d="M10.67 9.31a3.001 3.001 0 0 1 2.062 5.546 3 3 0 0 1-3.771-4.559 1.007 1.007 0 0 1-.095-.137l-4.5-7.794a1 1 0 0 1 1.732-1l4.5 7.794c.028.05.052.1.071.15zm-3.283.35l-.289.5c-.028.05-.06.095-.095.137a3.001 3.001 0 0 1-3.77 4.56A3 3 0 0 1 5.294 9.31c.02-.051.043-.102.071-.15l.866-1.5 1.155 2zm2.31-4l-1.156-2 1.325-2.294a1 1 0 0 1 1.732 1L9.696 5.66zm-5.465 7.464a1 1 0 1 0 1-1.732 1 1 0 0 0-1 1.732zm7.5 0a1 1 0 1 0-1-1.732 1 1 0 0 0 1 1.732z"/></symbol> - <symbol viewBox="0 0 16 16" id="spam" xmlns="http://www.w3.org/2000/svg"><path d="M8.75.433l5.428 3.134a1.5 1.5 0 0 1 .75 1.299v6.268a1.5 1.5 0 0 1-.75 1.299L8.75 15.567a1.5 1.5 0 0 1-1.5 0l-5.428-3.134a1.5 1.5 0 0 1-.75-1.299V4.866a1.5 1.5 0 0 1 .75-1.299L7.25.433a1.5 1.5 0 0 1 1.5 0zM3.072 5.155v5.69L8 13.691l4.928-2.846v-5.69L8 2.309 3.072 5.155zM8 4a1 1 0 0 1 1 1v3a1 1 0 1 1-2 0V5a1 1 0 0 1 1-1zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol> - <symbol viewBox="0 0 16 16" id="star" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7.609 14.394l-3.465 1.473a1 1 0 0 1-1.39-.989l.276-4.024a1 1 0 0 0-.219-.694L.303 7.037A1 1 0 0 1 .83 5.443l3.715-.964a1 1 0 0 0 .609-.457L7.14.682a1 1 0 0 1 1.72 0l1.985 3.34a1 1 0 0 0 .609.457l3.715.964a1 1 0 0 1 .528 1.594L13.19 10.16a1 1 0 0 0-.219.694l.275 4.024a1 1 0 0 1-1.389.989l-3.465-1.473a1 1 0 0 0-.782 0z"/></symbol> - <symbol viewBox="0 0 16 16" id="star-o" xmlns="http://www.w3.org/2000/svg"><path d="M10.975 10.99a3 3 0 0 1 .655-2.083l1.54-1.916-2.219-.576a3 3 0 0 1-1.825-1.37L8 3.15 6.874 5.044a3 3 0 0 1-1.825 1.371l-2.218.576 1.54 1.916a3 3 0 0 1 .654 2.083l-.165 2.4 1.965-.836a3 3 0 0 1 2.348 0l1.965.836-.164-2.399zM7.61 14.394l-3.465 1.473a1 1 0 0 1-1.39-.989l.276-4.024a1 1 0 0 0-.219-.694L.303 7.037A1 1 0 0 1 .83 5.443l3.715-.964a1 1 0 0 0 .609-.457L7.14.682a1 1 0 0 1 1.72 0l1.985 3.34a1 1 0 0 0 .609.457l3.715.964a1 1 0 0 1 .528 1.594L13.19 10.16a1 1 0 0 0-.219.694l.275 4.024a1 1 0 0 1-1.389.989l-3.465-1.473a1 1 0 0 0-.782 0z"/></symbol> - <symbol viewBox="0 0 16 16" id="stop" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M2 0h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2z"/></symbol> - <symbol viewBox="0 0 16 16" id="talic" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M6 0h7a1 1 0 0 1 0 2H6a1 1 0 1 1 0-2zm2 2h3L8 14H5L8 2zM3 14h7a1 1 0 0 1 0 2H3a1 1 0 0 1 0-2z"/></symbol> - <symbol viewBox="0 0 16 16" id="task-done" xmlns="http://www.w3.org/2000/svg"><path d="M7.536 8.657l2.828-2.829a1 1 0 0 1 1.414 1.415l-3.535 3.535a.997.997 0 0 1-1.415 0l-2.12-2.121A1 1 0 0 1 6.12 7.243l1.415 1.414zM3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3z"/></symbol> - <symbol viewBox="0 0 16 16" id="template" xmlns="http://www.w3.org/2000/svg"><path d="M3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3zm.8 2h2.4a.8.8 0 0 1 .8.8v1.4a.8.8 0 0 1-.8.8H3.8a.8.8 0 0 1-.8-.8V4.8a.8.8 0 0 1 .8-.8zm4.7 0h4a.5.5 0 1 1 0 1h-4a.5.5 0 0 1 0-1zm0 2h4a.5.5 0 1 1 0 1h-4a.5.5 0 0 1 0-1zm-5 3h9a.5.5 0 1 1 0 1h-9a.5.5 0 0 1 0-1zm0 2h9a.5.5 0 1 1 0 1h-9a.5.5 0 1 1 0-1z"/></symbol> - <symbol viewBox="0 0 16 16" id="thump-down" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8.33 11h5.282a2 2 0 0 0 1.963-2.38l-.563-2.905a3 3 0 0 0-.243-.732l-1.103-2.286A3 3 0 0 0 10.964 1H7a3 3 0 0 0-3 3v6.3a2 2 0 0 0 .436 1.247l3.11 3.9a.632.632 0 0 0 .941.053l.137-.137a1 1 0 0 0 .28-.87L8.329 11zM1 10h2V3H1a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1z"/></symbol> - <symbol viewBox="0 0 16 16" id="thump-up" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8.33 5h5.282a2 2 0 0 1 1.963 2.38l-.563 2.905a3 3 0 0 1-.243.732l-1.103 2.286A3 3 0 0 1 10.964 15H7a3 3 0 0 1-3-3V5.7a2 2 0 0 1 .436-1.247l3.11-3.9A.632.632 0 0 1 8.487.5l.137.137a1 1 0 0 1 .28.87L8.329 5zM1 6h2v7H1a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1z"/></symbol> - <symbol viewBox="0 0 16 16" id="timer" xmlns="http://www.w3.org/2000/svg"><path d="M12.022 3.27l.77-.77a1 1 0 0 1 1.415 1.414l-.728.729a7 7 0 1 1-1.456-1.372zM8 14A5 5 0 1 0 8 4a5 5 0 0 0 0 10zm0-9a1 1 0 0 1 1 1v2a1 1 0 1 1-2 0V6a1 1 0 0 1 1-1zM6 0h4a1 1 0 0 1 0 2H6a1 1 0 1 1 0-2z"/></symbol> - <symbol viewBox="0 0 16 16" id="todo-add" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 4V2a1 1 0 0 1 2 0v2h2a1 1 0 0 1 0 2h-2v2a1 1 0 0 1-2 0V6H8a1 1 0 1 1 0-2h2zm2 7a1 1 0 0 1 2 0v2a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3h2a1 1 0 1 1 0 2H3a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-2z"/></symbol> - <symbol viewBox="0 0 16 16" id="todo-done" xmlns="http://www.w3.org/2000/svg"><path d="M8.243 7.485l4.95-4.95a1 1 0 1 1 1.414 1.415L8.95 9.607a.997.997 0 0 1-1.414 0L4.707 6.778a1 1 0 0 1 1.414-1.414l2.122 2.121zM12 11a1 1 0 0 1 2 0v2a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3h2a1 1 0 1 1 0 2H3a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-2z"/></symbol> - <symbol viewBox="0 0 16 16" id="token" xmlns="http://www.w3.org/2000/svg"><path d="M3 2h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H3zm1 5a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol> - <symbol viewBox="0 0 16 16" id="unapproval" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M11.95 8.536l1.06-1.061a1 1 0 0 1 1.415 1.414l-1.061 1.06 1.06 1.061a1 1 0 0 1-1.414 1.415l-1.06-1.061-1.06 1.06a1 1 0 1 1-1.415-1.414l1.06-1.06-1.06-1.06a1 1 0 0 1 1.414-1.415l1.06 1.06zm-3.768-.33c.006.503.201 1.006.586 1.39l.353.354-.353.353a2 2 0 1 0 2.828 2.829l.354-.354.047.048C11.964 14.363 11.527 15 6 15c-5.924 0-6-.78-6-2.52S.964 8 6 8c.834 0 1.557.074 2.182.205zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6z"/></symbol> - <symbol viewBox="0 0 16 16" id="unassignee" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M11 5h4a1 1 0 0 1 0 2h-4a1 1 0 0 1 0-2zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6zM6 15c-5.924 0-6-.78-6-2.52S.964 8 6 8s6 2.692 6 4.48c0 1.788-.076 2.52-6 2.52z"/></symbol> - <symbol viewBox="0 0 16 16" id="unlink" xmlns="http://www.w3.org/2000/svg"><path d="M11.295 8.845l-.659-1.664a1.78 1.78 0 0 0 .04-.04l1.415-1.414c.586-.586.654-1.468.152-1.97s-1.384-.434-1.97.152L8.859 5.323a1.781 1.781 0 0 0-.04.04l-1.664-.658c.141-.208.305-.408.491-.594l1.415-1.414c1.366-1.367 3.424-1.525 4.596-.354 1.171 1.172 1.013 3.23-.354 4.596L11.89 8.354c-.186.186-.386.35-.594.491zm-2.45 2.45a4.075 4.075 0 0 1-.491.594l-1.415 1.414c-1.366 1.367-3.424 1.525-4.596.354-1.171-1.172-1.013-3.23.354-4.596L4.11 7.646c.186-.186.386-.35.594-.491l.659 1.664a1.781 1.781 0 0 0-.04.04l-1.415 1.414c-.586.586-.654 1.468-.152 1.97s1.384.434 1.97-.152l1.414-1.414a1.78 1.78 0 0 0 .04-.04l1.664.658zm3.812-2.088h2a.5.5 0 0 1 .5.5v.05a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-.05a.5.5 0 0 1 .5-.5zm-.384 2.116l1.415 1.414a.5.5 0 0 1 0 .708l-.037.036a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 0-.707l.036-.037a.5.5 0 0 1 .707 0zm-2.823 1.09a.5.5 0 0 1 .5-.5h.052a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.5.5H9.95a.5.5 0 0 1-.5-.5v-2zm-2.748-9.16a.5.5 0 0 1-.5.5h-.05a.5.5 0 0 1-.5-.5v-2a.5.5 0 0 1 .5-.5h.05a.5.5 0 0 1 .5.5v2zm-2.116.383a.5.5 0 0 1 0 .707l-.036.036a.5.5 0 0 1-.707 0L2.428 2.965a.5.5 0 0 1 0-.707l.037-.036a.5.5 0 0 1 .707 0l1.414 1.414zm-1.09 2.823h-2a.5.5 0 0 1-.5-.5v-.051a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v.05a.5.5 0 0 1-.5.5z"/></symbol> - <symbol viewBox="0 0 16 16" id="user" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0 8c-6.888 0-6.976-.78-6.976-2.52S2.144 8 8 8s6.976 2.692 6.976 4.48c0 1.788-.088 2.52-6.976 2.52z"/></symbol> - <symbol viewBox="0 0 16 16" id="users" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10.521 8.01C15.103 8.19 16 10.755 16 12.48c0 1.533-.056 2.29-3.808 2.475.609-.54.808-1.331.808-2.475 0-1.911-.804-3.503-2.479-4.47zm-1.67-1.228A3.987 3.987 0 0 0 9.976 4a3.987 3.987 0 0 0-1.125-2.782 3 3 0 1 1 0 5.563zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6zM6 15c-5.924 0-6-.78-6-2.52S.964 8 6 8s6 2.692 6 4.48c0 1.788-.076 2.52-6 2.52z"/></symbol> - <symbol viewBox="0 0 16 16" id="volume-up" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M1 5h1v6H1a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1zm2 0l4.445-2.964A1 1 0 0 1 9 2.87v10.26a1 1 0 0 1-1.555.833L3 11V5zm10.283 7.89a.5.5 0 0 1-.66-.752A5.485 5.485 0 0 0 14.5 8c0-1.601-.687-3.09-1.865-4.128a.5.5 0 0 1 .661-.75A6.484 6.484 0 0 1 15.5 8a6.485 6.485 0 0 1-2.217 4.89zm-2.002-2.236a.5.5 0 1 1-.652-.758c.55-.472.871-1.157.871-1.896 0-.732-.315-1.411-.856-1.883a.5.5 0 0 1 .658-.753A3.492 3.492 0 0 1 12.5 8c0 1.033-.45 1.994-1.219 2.654z"/></symbol> - <symbol viewBox="0 0 16 16" id="warning" xmlns="http://www.w3.org/2000/svg"><path d="M15.34 10.479A3 3 0 0 1 12.756 15h-9.51A3 3 0 0 1 .66 10.479l4.755-8.083a3 3 0 0 1 5.172 0l4.755 8.083zm-6.478-7.07a1 1 0 0 0-1.724 0l-4.755 8.084A1 1 0 0 0 3.245 13h9.51a1 1 0 0 0 .862-1.507L8.862 3.41zM8 5a1 1 0 0 1 1 1v2a1 1 0 1 1-2 0V6a1 1 0 0 1 1-1zm0 7a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></symbol> - <symbol viewBox="0 0 16 16" id="work" xmlns="http://www.w3.org/2000/svg"><path d="M12 3h1a3 3 0 0 1 3 3v7a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V6a3 3 0 0 1 3-3h1V2a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v1zM6 2v1h4V2H6zM3 5a1 1 0 0 0-1 1v7a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1H3zm1.5 1a.5.5 0 0 1 .5.5v6a.5.5 0 1 1-1 0v-6a.5.5 0 0 1 .5-.5zm7 0a.5.5 0 0 1 .5.5v6a.5.5 0 1 1-1 0v-6a.5.5 0 0 1 .5-.5z"/></symbol> -</svg> - -<!-- -==================================================================================================== ---> - - <header> - <h1>SVG <code><symbol></code> sprite preview</h1> - <p>This preview features two methods of using the generated sprite in conjunction with inline SVG. Please have a look at the HTML source for further details and be aware of the following constraints:</p> - <ul> - <li>Your browser has to <a href="http://caniuse.com/#feat=svg-html5" target="_blank">support inline SVG</a> for these techniques to work.</li> - <li>The embedded sprite (A) slightly differs from the generated external one. Please <a href="https://github.com/jkphl/svg-sprite/blob/master/docs/configuration.md#defs--symbol-mode" target="_blank">see the documentation</a> for details on how to create such an embeddable sprite.</li> - <li>Internet Explorer up to version 11 doesn't support external sprites for use with inline SVG. For IE 9-11, you may polyfill this functionality with <a href="https://github.com/jonathantneal/svg4everybody" target="_blank">SVG for Everybody</a>.</li> - </ul> - </header> - <section> - -<!-- - -A) Inline SVG with embedded sprite -==================================================================================================== -These SVG images make use of fragment identifiers (IDs) and are extracted out of the inline sprite -embedded above. They may be styled via CSS. - ---> - - <h3>A) Inline SVG with embedded sprite</h3> - <ul> - - <li title="abuse"> - <div class="icon-box"> - - <!-- abuse --> - <svg class="svg-abuse-dims"> - <use xlink:href="#abuse"></use> - </svg> - - </div> - <h2>abuse</h2> - </li> - <li title="account"> - <div class="icon-box"> - - <!-- account --> - <svg class="svg-account-dims"> - <use xlink:href="#account"></use> - </svg> - - </div> - <h2>account</h2> - </li> - <li title="admin"> - <div class="icon-box"> - - <!-- admin --> - <svg class="svg-admin-dims"> - <use xlink:href="#admin"></use> - </svg> - - </div> - <h2>admin</h2> - </li> - <li title="angle-double-left"> - <div class="icon-box"> - - <!-- angle-double-left --> - <svg class="svg-angle-double-left-dims"> - <use xlink:href="#angle-double-left"></use> - </svg> - - </div> - <h2>angle-double-left</h2> - </li> - <li title="angle-down"> - <div class="icon-box"> - - <!-- angle-down --> - <svg class="svg-angle-down-dims"> - <use xlink:href="#angle-down"></use> - </svg> - - </div> - <h2>angle-down</h2> - </li> - <li title="angle-left"> - <div class="icon-box"> - - <!-- angle-left --> - <svg class="svg-angle-left-dims"> - <use xlink:href="#angle-left"></use> - </svg> - - </div> - <h2>angle-left</h2> - </li> - <li title="angle-right"> - <div class="icon-box"> - - <!-- angle-right --> - <svg class="svg-angle-right-dims"> - <use xlink:href="#angle-right"></use> - </svg> - - </div> - <h2>angle-right</h2> - </li> - <li title="angle-up"> - <div class="icon-box"> - - <!-- angle-up --> - <svg class="svg-angle-up-dims"> - <use xlink:href="#angle-up"></use> - </svg> - - </div> - <h2>angle-up</h2> - </li> - <li title="appearance"> - <div class="icon-box"> - - <!-- appearance --> - <svg class="svg-appearance-dims"> - <use xlink:href="#appearance"></use> - </svg> - - </div> - <h2>appearance</h2> - </li> - <li title="applications"> - <div class="icon-box"> - - <!-- applications --> - <svg class="svg-applications-dims"> - <use xlink:href="#applications"></use> - </svg> - - </div> - <h2>applications</h2> - </li> - <li title="approval"> - <div class="icon-box"> - - <!-- approval --> - <svg class="svg-approval-dims"> - <use xlink:href="#approval"></use> - </svg> - - </div> - <h2>approval</h2> - </li> - <li title="arrow-right"> - <div class="icon-box"> - - <!-- arrow-right --> - <svg class="svg-arrow-right-dims"> - <use xlink:href="#arrow-right"></use> - </svg> - - </div> - <h2>arrow-right</h2> - </li> - <li title="assignee"> - <div class="icon-box"> - - <!-- assignee --> - <svg class="svg-assignee-dims"> - <use xlink:href="#assignee"></use> - </svg> - - </div> - <h2>assignee</h2> - </li> - <li title="bold"> - <div class="icon-box"> - - <!-- bold --> - <svg class="svg-bold-dims"> - <use xlink:href="#bold"></use> - </svg> - - </div> - <h2>bold</h2> - </li> - <li title="book"> - <div class="icon-box"> - - <!-- book --> - <svg class="svg-book-dims"> - <use xlink:href="#book"></use> - </svg> - - </div> - <h2>book</h2> - </li> - <li title="branch"> - <div class="icon-box"> - - <!-- branch --> - <svg class="svg-branch-dims"> - <use xlink:href="#branch"></use> - </svg> - - </div> - <h2>branch</h2> - </li> - <li title="calendar"> - <div class="icon-box"> - - <!-- calendar --> - <svg class="svg-calendar-dims"> - <use xlink:href="#calendar"></use> - </svg> - - </div> - <h2>calendar</h2> - </li> - <li title="cancel"> - <div class="icon-box"> - - <!-- cancel --> - <svg class="svg-cancel-dims"> - <use xlink:href="#cancel"></use> - </svg> - - </div> - <h2>cancel</h2> - </li> - <li title="chevron-down"> - <div class="icon-box"> - - <!-- chevron-down --> - <svg class="svg-chevron-down-dims"> - <use xlink:href="#chevron-down"></use> - </svg> - - </div> - <h2>chevron-down</h2> - </li> - <li title="chevron-left"> - <div class="icon-box"> - - <!-- chevron-left --> - <svg class="svg-chevron-left-dims"> - <use xlink:href="#chevron-left"></use> - </svg> - - </div> - <h2>chevron-left</h2> - </li> - <li title="chevron-right"> - <div class="icon-box"> - - <!-- chevron-right --> - <svg class="svg-chevron-right-dims"> - <use xlink:href="#chevron-right"></use> - </svg> - - </div> - <h2>chevron-right</h2> - </li> - <li title="chevron-up"> - <div class="icon-box"> - - <!-- chevron-up --> - <svg class="svg-chevron-up-dims"> - <use xlink:href="#chevron-up"></use> - </svg> - - </div> - <h2>chevron-up</h2> - </li> - <li title="clock"> - <div class="icon-box"> - - <!-- clock --> - <svg class="svg-clock-dims"> - <use xlink:href="#clock"></use> - </svg> - - </div> - <h2>clock</h2> - </li> - <li title="code"> - <div class="icon-box"> - - <!-- code --> - <svg class="svg-code-dims"> - <use xlink:href="#code"></use> - </svg> - - </div> - <h2>code</h2> - </li> - <li title="comment"> - <div class="icon-box"> - - <!-- comment --> - <svg class="svg-comment-dims"> - <use xlink:href="#comment"></use> - </svg> - - </div> - <h2>comment</h2> - </li> - <li title="comment-dots"> - <div class="icon-box"> - - <!-- comment-dots --> - <svg class="svg-comment-dots-dims"> - <use xlink:href="#comment-dots"></use> - </svg> - - </div> - <h2>comment-dots</h2> - </li> - <li title="comment-next"> - <div class="icon-box"> - - <!-- comment-next --> - <svg class="svg-comment-next-dims"> - <use xlink:href="#comment-next"></use> - </svg> - - </div> - <h2>comment-next</h2> - </li> - <li title="comments"> - <div class="icon-box"> - - <!-- comments --> - <svg class="svg-comments-dims"> - <use xlink:href="#comments"></use> - </svg> - - </div> - <h2>comments</h2> - </li> - <li title="commit"> - <div class="icon-box"> - - <!-- commit --> - <svg class="svg-commit-dims"> - <use xlink:href="#commit"></use> - </svg> - - </div> - <h2>commit</h2> - </li> - <li title="credit-card"> - <div class="icon-box"> - - <!-- credit-card --> - <svg class="svg-credit-card-dims"> - <use xlink:href="#credit-card"></use> - </svg> - - </div> - <h2>credit-card</h2> - </li> - <li title="disk"> - <div class="icon-box"> - - <!-- disk --> - <svg class="svg-disk-dims"> - <use xlink:href="#disk"></use> - </svg> - - </div> - <h2>disk</h2> - </li> - <li title="doc_code"> - <div class="icon-box"> - - <!-- doc_code --> - <svg class="svg-doc_code-dims"> - <use xlink:href="#doc_code"></use> - </svg> - - </div> - <h2>doc_code</h2> - </li> - <li title="doc_image"> - <div class="icon-box"> - - <!-- doc_image --> - <svg class="svg-doc_image-dims"> - <use xlink:href="#doc_image"></use> - </svg> - - </div> - <h2>doc_image</h2> - </li> - <li title="doc_text"> - <div class="icon-box"> - - <!-- doc_text --> - <svg class="svg-doc_text-dims"> - <use xlink:href="#doc_text"></use> - </svg> - - </div> - <h2>doc_text</h2> - </li> - <li title="download"> - <div class="icon-box"> - - <!-- download --> - <svg class="svg-download-dims"> - <use xlink:href="#download"></use> - </svg> - - </div> - <h2>download</h2> - </li> - <li title="duplicate"> - <div class="icon-box"> - - <!-- duplicate --> - <svg class="svg-duplicate-dims"> - <use xlink:href="#duplicate"></use> - </svg> - - </div> - <h2>duplicate</h2> - </li> - <li title="earth"> - <div class="icon-box"> - - <!-- earth --> - <svg class="svg-earth-dims"> - <use xlink:href="#earth"></use> - </svg> - - </div> - <h2>earth</h2> - </li> - <li title="eye"> - <div class="icon-box"> - - <!-- eye --> - <svg class="svg-eye-dims"> - <use xlink:href="#eye"></use> - </svg> - - </div> - <h2>eye</h2> - </li> - <li title="eye-slash"> - <div class="icon-box"> - - <!-- eye-slash --> - <svg class="svg-eye-slash-dims"> - <use xlink:href="#eye-slash"></use> - </svg> - - </div> - <h2>eye-slash</h2> - </li> - <li title="file-additions"> - <div class="icon-box"> - - <!-- file-additions --> - <svg class="svg-file-additions-dims"> - <use xlink:href="#file-additions"></use> - </svg> - - </div> - <h2>file-additions</h2> - </li> - <li title="file-deletion"> - <div class="icon-box"> - - <!-- file-deletion --> - <svg class="svg-file-deletion-dims"> - <use xlink:href="#file-deletion"></use> - </svg> - - </div> - <h2>file-deletion</h2> - </li> - <li title="file-modified"> - <div class="icon-box"> - - <!-- file-modified --> - <svg class="svg-file-modified-dims"> - <use xlink:href="#file-modified"></use> - </svg> - - </div> - <h2>file-modified</h2> - </li> - <li title="filter"> - <div class="icon-box"> - - <!-- filter --> - <svg class="svg-filter-dims"> - <use xlink:href="#filter"></use> - </svg> - - </div> - <h2>filter</h2> - </li> - <li title="folder"> - <div class="icon-box"> - - <!-- folder --> - <svg class="svg-folder-dims"> - <use xlink:href="#folder"></use> - </svg> - - </div> - <h2>folder</h2> - </li> - <li title="fork"> - <div class="icon-box"> - - <!-- fork --> - <svg class="svg-fork-dims"> - <use xlink:href="#fork"></use> - </svg> - - </div> - <h2>fork</h2> - </li> - <li title="git-merge"> - <div class="icon-box"> - - <!-- git-merge --> - <svg class="svg-git-merge-dims"> - <use xlink:href="#git-merge"></use> - </svg> - - </div> - <h2>git-merge</h2> - </li> - <li title="group"> - <div class="icon-box"> - - <!-- group --> - <svg class="svg-group-dims"> - <use xlink:href="#group"></use> - </svg> - - </div> - <h2>group</h2> - </li> - <li title="history"> - <div class="icon-box"> - - <!-- history --> - <svg class="svg-history-dims"> - <use xlink:href="#history"></use> - </svg> - - </div> - <h2>history</h2> - </li> - <li title="home"> - <div class="icon-box"> - - <!-- home --> - <svg class="svg-home-dims"> - <use xlink:href="#home"></use> - </svg> - - </div> - <h2>home</h2> - </li> - <li title="hook"> - <div class="icon-box"> - - <!-- hook --> - <svg class="svg-hook-dims"> - <use xlink:href="#hook"></use> - </svg> - - </div> - <h2>hook</h2> - </li> - <li title="issue-block"> - <div class="icon-box"> - - <!-- issue-block --> - <svg class="svg-issue-block-dims"> - <use xlink:href="#issue-block"></use> - </svg> - - </div> - <h2>issue-block</h2> - </li> - <li title="issue-child"> - <div class="icon-box"> - - <!-- issue-child --> - <svg class="svg-issue-child-dims"> - <use xlink:href="#issue-child"></use> - </svg> - - </div> - <h2>issue-child</h2> - </li> - <li title="issue-close"> - <div class="icon-box"> - - <!-- issue-close --> - <svg class="svg-issue-close-dims"> - <use xlink:href="#issue-close"></use> - </svg> - - </div> - <h2>issue-close</h2> - </li> - <li title="issue-duplicate"> - <div class="icon-box"> - - <!-- issue-duplicate --> - <svg class="svg-issue-duplicate-dims"> - <use xlink:href="#issue-duplicate"></use> - </svg> - - </div> - <h2>issue-duplicate</h2> - </li> - <li title="issue-new"> - <div class="icon-box"> - - <!-- issue-new --> - <svg class="svg-issue-new-dims"> - <use xlink:href="#issue-new"></use> - </svg> - - </div> - <h2>issue-new</h2> - </li> - <li title="issue-open"> - <div class="icon-box"> - - <!-- issue-open --> - <svg class="svg-issue-open-dims"> - <use xlink:href="#issue-open"></use> - </svg> - - </div> - <h2>issue-open</h2> - </li> - <li title="issue-open-m"> - <div class="icon-box"> - - <!-- issue-open-m --> - <svg class="svg-issue-open-m-dims"> - <use xlink:href="#issue-open-m"></use> - </svg> - - </div> - <h2>issue-open-m</h2> - </li> - <li title="issue-parent"> - <div class="icon-box"> - - <!-- issue-parent --> - <svg class="svg-issue-parent-dims"> - <use xlink:href="#issue-parent"></use> - </svg> - - </div> - <h2>issue-parent</h2> - </li> - <li title="issues"> - <div class="icon-box"> - - <!-- issues --> - <svg class="svg-issues-dims"> - <use xlink:href="#issues"></use> - </svg> - - </div> - <h2>issues</h2> - </li> - <li title="key"> - <div class="icon-box"> - - <!-- key --> - <svg class="svg-key-dims"> - <use xlink:href="#key"></use> - </svg> - - </div> - <h2>key</h2> - </li> - <li title="key-2"> - <div class="icon-box"> - - <!-- key-2 --> - <svg class="svg-key-2-dims"> - <use xlink:href="#key-2"></use> - </svg> - - </div> - <h2>key-2</h2> - </li> - <li title="label"> - <div class="icon-box"> - - <!-- label --> - <svg class="svg-label-dims"> - <use xlink:href="#label"></use> - </svg> - - </div> - <h2>label</h2> - </li> - <li title="labels"> - <div class="icon-box"> - - <!-- labels --> - <svg class="svg-labels-dims"> - <use xlink:href="#labels"></use> - </svg> - - </div> - <h2>labels</h2> - </li> - <li title="leave"> - <div class="icon-box"> - - <!-- leave --> - <svg class="svg-leave-dims"> - <use xlink:href="#leave"></use> - </svg> - - </div> - <h2>leave</h2> - </li> - <li title="level-up"> - <div class="icon-box"> - - <!-- level-up --> - <svg class="svg-level-up-dims"> - <use xlink:href="#level-up"></use> - </svg> - - </div> - <h2>level-up</h2> - </li> - <li title="license"> - <div class="icon-box"> - - <!-- license --> - <svg class="svg-license-dims"> - <use xlink:href="#license"></use> - </svg> - - </div> - <h2>license</h2> - </li> - <li title="link"> - <div class="icon-box"> - - <!-- link --> - <svg class="svg-link-dims"> - <use xlink:href="#link"></use> - </svg> - - </div> - <h2>link</h2> - </li> - <li title="list-bulleted"> - <div class="icon-box"> - - <!-- list-bulleted --> - <svg class="svg-list-bulleted-dims"> - <use xlink:href="#list-bulleted"></use> - </svg> - - </div> - <h2>list-bulleted</h2> - </li> - <li title="list-numbered"> - <div class="icon-box"> - - <!-- list-numbered --> - <svg class="svg-list-numbered-dims"> - <use xlink:href="#list-numbered"></use> - </svg> - - </div> - <h2>list-numbered</h2> - </li> - <li title="location"> - <div class="icon-box"> - - <!-- location --> - <svg class="svg-location-dims"> - <use xlink:href="#location"></use> - </svg> - - </div> - <h2>location</h2> - </li> - <li title="location-dot"> - <div class="icon-box"> - - <!-- location-dot --> - <svg class="svg-location-dot-dims"> - <use xlink:href="#location-dot"></use> - </svg> - - </div> - <h2>location-dot</h2> - </li> - <li title="lock"> - <div class="icon-box"> - - <!-- lock --> - <svg class="svg-lock-dims"> - <use xlink:href="#lock"></use> - </svg> - - </div> - <h2>lock</h2> - </li> - <li title="lock-open"> - <div class="icon-box"> - - <!-- lock-open --> - <svg class="svg-lock-open-dims"> - <use xlink:href="#lock-open"></use> - </svg> - - </div> - <h2>lock-open</h2> - </li> - <li title="log"> - <div class="icon-box"> - - <!-- log --> - <svg class="svg-log-dims"> - <use xlink:href="#log"></use> - </svg> - - </div> - <h2>log</h2> - </li> - <li title="mail"> - <div class="icon-box"> - - <!-- mail --> - <svg class="svg-mail-dims"> - <use xlink:href="#mail"></use> - </svg> - - </div> - <h2>mail</h2> - </li> - <li title="merge-request-close"> - <div class="icon-box"> - - <!-- merge-request-close --> - <svg class="svg-merge-request-close-dims"> - <use xlink:href="#merge-request-close"></use> - </svg> - - </div> - <h2>merge-request-close</h2> - </li> - <li title="merge-request-close-m"> - <div class="icon-box"> - - <!-- merge-request-close-m --> - <svg class="svg-merge-request-close-m-dims"> - <use xlink:href="#merge-request-close-m"></use> - </svg> - - </div> - <h2>merge-request-close-m</h2> - </li> - <li title="messages"> - <div class="icon-box"> - - <!-- messages --> - <svg class="svg-messages-dims"> - <use xlink:href="#messages"></use> - </svg> - - </div> - <h2>messages</h2> - </li> - <li title="mobile-issue-close"> - <div class="icon-box"> - - <!-- mobile-issue-close --> - <svg class="svg-mobile-issue-close-dims"> - <use xlink:href="#mobile-issue-close"></use> - </svg> - - </div> - <h2>mobile-issue-close</h2> - </li> - <li title="monitor"> - <div class="icon-box"> - - <!-- monitor --> - <svg class="svg-monitor-dims"> - <use xlink:href="#monitor"></use> - </svg> - - </div> - <h2>monitor</h2> - </li> - <li title="more"> - <div class="icon-box"> - - <!-- more --> - <svg class="svg-more-dims"> - <use xlink:href="#more"></use> - </svg> - - </div> - <h2>more</h2> - </li> - <li title="notifications"> - <div class="icon-box"> - - <!-- notifications --> - <svg class="svg-notifications-dims"> - <use xlink:href="#notifications"></use> - </svg> - - </div> - <h2>notifications</h2> - </li> - <li title="notifications-off"> - <div class="icon-box"> - - <!-- notifications-off --> - <svg class="svg-notifications-off-dims"> - <use xlink:href="#notifications-off"></use> - </svg> - - </div> - <h2>notifications-off</h2> - </li> - <li title="overview"> - <div class="icon-box"> - - <!-- overview --> - <svg class="svg-overview-dims"> - <use xlink:href="#overview"></use> - </svg> - - </div> - <h2>overview</h2> - </li> - <li title="pencil"> - <div class="icon-box"> - - <!-- pencil --> - <svg class="svg-pencil-dims"> - <use xlink:href="#pencil"></use> - </svg> - - </div> - <h2>pencil</h2> - </li> - <li title="pipeline"> - <div class="icon-box"> - - <!-- pipeline --> - <svg class="svg-pipeline-dims"> - <use xlink:href="#pipeline"></use> - </svg> - - </div> - <h2>pipeline</h2> - </li> - <li title="play"> - <div class="icon-box"> - - <!-- play --> - <svg class="svg-play-dims"> - <use xlink:href="#play"></use> - </svg> - - </div> - <h2>play</h2> - </li> - <li title="plus"> - <div class="icon-box"> - - <!-- plus --> - <svg class="svg-plus-dims"> - <use xlink:href="#plus"></use> - </svg> - - </div> - <h2>plus</h2> - </li> - <li title="plus-square"> - <div class="icon-box"> - - <!-- plus-square --> - <svg class="svg-plus-square-dims"> - <use xlink:href="#plus-square"></use> - </svg> - - </div> - <h2>plus-square</h2> - </li> - <li title="plus-square-o"> - <div class="icon-box"> - - <!-- plus-square-o --> - <svg class="svg-plus-square-o-dims"> - <use xlink:href="#plus-square-o"></use> - </svg> - - </div> - <h2>plus-square-o</h2> - </li> - <li title="preferences"> - <div class="icon-box"> - - <!-- preferences --> - <svg class="svg-preferences-dims"> - <use xlink:href="#preferences"></use> - </svg> - - </div> - <h2>preferences</h2> - </li> - <li title="profile"> - <div class="icon-box"> - - <!-- profile --> - <svg class="svg-profile-dims"> - <use xlink:href="#profile"></use> - </svg> - - </div> - <h2>profile</h2> - </li> - <li title="project"> - <div class="icon-box"> - - <!-- project --> - <svg class="svg-project-dims"> - <use xlink:href="#project"></use> - </svg> - - </div> - <h2>project</h2> - </li> - <li title="push-rules"> - <div class="icon-box"> - - <!-- push-rules --> - <svg class="svg-push-rules-dims"> - <use xlink:href="#push-rules"></use> - </svg> - - </div> - <h2>push-rules</h2> - </li> - <li title="question"> - <div class="icon-box"> - - <!-- question --> - <svg class="svg-question-dims"> - <use xlink:href="#question"></use> - </svg> - - </div> - <h2>question</h2> - </li> - <li title="question-o"> - <div class="icon-box"> - - <!-- question-o --> - <svg class="svg-question-o-dims"> - <use xlink:href="#question-o"></use> - </svg> - - </div> - <h2>question-o</h2> - </li> - <li title="quote"> - <div class="icon-box"> - - <!-- quote --> - <svg class="svg-quote-dims"> - <use xlink:href="#quote"></use> - </svg> - - </div> - <h2>quote</h2> - </li> - <li title="redo"> - <div class="icon-box"> - - <!-- redo --> - <svg class="svg-redo-dims"> - <use xlink:href="#redo"></use> - </svg> - - </div> - <h2>redo</h2> - </li> - <li title="remove"> - <div class="icon-box"> - - <!-- remove --> - <svg class="svg-remove-dims"> - <use xlink:href="#remove"></use> - </svg> - - </div> - <h2>remove</h2> - </li> - <li title="repeat"> - <div class="icon-box"> - - <!-- repeat --> - <svg class="svg-repeat-dims"> - <use xlink:href="#repeat"></use> - </svg> - - </div> - <h2>repeat</h2> - </li> - <li title="retry"> - <div class="icon-box"> - - <!-- retry --> - <svg class="svg-retry-dims"> - <use xlink:href="#retry"></use> - </svg> - - </div> - <h2>retry</h2> - </li> - <li title="scale"> - <div class="icon-box"> - - <!-- scale --> - <svg class="svg-scale-dims"> - <use xlink:href="#scale"></use> - </svg> - - </div> - <h2>scale</h2> - </li> - <li title="screen-full"> - <div class="icon-box"> - - <!-- screen-full --> - <svg class="svg-screen-full-dims"> - <use xlink:href="#screen-full"></use> - </svg> - - </div> - <h2>screen-full</h2> - </li> - <li title="screen-normal"> - <div class="icon-box"> - - <!-- screen-normal --> - <svg class="svg-screen-normal-dims"> - <use xlink:href="#screen-normal"></use> - </svg> - - </div> - <h2>screen-normal</h2> - </li> - <li title="search"> - <div class="icon-box"> - - <!-- search --> - <svg class="svg-search-dims"> - <use xlink:href="#search"></use> - </svg> - - </div> - <h2>search</h2> - </li> - <li title="settings"> - <div class="icon-box"> - - <!-- settings --> - <svg class="svg-settings-dims"> - <use xlink:href="#settings"></use> - </svg> - - </div> - <h2>settings</h2> - </li> - <li title="shield"> - <div class="icon-box"> - - <!-- shield --> - <svg class="svg-shield-dims"> - <use xlink:href="#shield"></use> - </svg> - - </div> - <h2>shield</h2> - </li> - <li title="slight-frown"> - <div class="icon-box"> - - <!-- slight-frown --> - <svg class="svg-slight-frown-dims"> - <use xlink:href="#slight-frown"></use> - </svg> - - </div> - <h2>slight-frown</h2> - </li> - <li title="slight-smile"> - <div class="icon-box"> - - <!-- slight-smile --> - <svg class="svg-slight-smile-dims"> - <use xlink:href="#slight-smile"></use> - </svg> - - </div> - <h2>slight-smile</h2> - </li> - <li title="smile"> - <div class="icon-box"> - - <!-- smile --> - <svg class="svg-smile-dims"> - <use xlink:href="#smile"></use> - </svg> - - </div> - <h2>smile</h2> - </li> - <li title="smiley"> - <div class="icon-box"> - - <!-- smiley --> - <svg class="svg-smiley-dims"> - <use xlink:href="#smiley"></use> - </svg> - - </div> - <h2>smiley</h2> - </li> - <li title="snippet"> - <div class="icon-box"> - - <!-- snippet --> - <svg class="svg-snippet-dims"> - <use xlink:href="#snippet"></use> - </svg> - - </div> - <h2>snippet</h2> - </li> - <li title="spam"> - <div class="icon-box"> - - <!-- spam --> - <svg class="svg-spam-dims"> - <use xlink:href="#spam"></use> - </svg> - - </div> - <h2>spam</h2> - </li> - <li title="star"> - <div class="icon-box"> - - <!-- star --> - <svg class="svg-star-dims"> - <use xlink:href="#star"></use> - </svg> - - </div> - <h2>star</h2> - </li> - <li title="star-o"> - <div class="icon-box"> - - <!-- star-o --> - <svg class="svg-star-o-dims"> - <use xlink:href="#star-o"></use> - </svg> - - </div> - <h2>star-o</h2> - </li> - <li title="stop"> - <div class="icon-box"> - - <!-- stop --> - <svg class="svg-stop-dims"> - <use xlink:href="#stop"></use> - </svg> - - </div> - <h2>stop</h2> - </li> - <li title="talic"> - <div class="icon-box"> - - <!-- talic --> - <svg class="svg-talic-dims"> - <use xlink:href="#talic"></use> - </svg> - - </div> - <h2>talic</h2> - </li> - <li title="task-done"> - <div class="icon-box"> - - <!-- task-done --> - <svg class="svg-task-done-dims"> - <use xlink:href="#task-done"></use> - </svg> - - </div> - <h2>task-done</h2> - </li> - <li title="template"> - <div class="icon-box"> - - <!-- template --> - <svg class="svg-template-dims"> - <use xlink:href="#template"></use> - </svg> - - </div> - <h2>template</h2> - </li> - <li title="thump-down"> - <div class="icon-box"> - - <!-- thump-down --> - <svg class="svg-thump-down-dims"> - <use xlink:href="#thump-down"></use> - </svg> - - </div> - <h2>thump-down</h2> - </li> - <li title="thump-up"> - <div class="icon-box"> - - <!-- thump-up --> - <svg class="svg-thump-up-dims"> - <use xlink:href="#thump-up"></use> - </svg> - - </div> - <h2>thump-up</h2> - </li> - <li title="timer"> - <div class="icon-box"> - - <!-- timer --> - <svg class="svg-timer-dims"> - <use xlink:href="#timer"></use> - </svg> - - </div> - <h2>timer</h2> - </li> - <li title="todo-add"> - <div class="icon-box"> - - <!-- todo-add --> - <svg class="svg-todo-add-dims"> - <use xlink:href="#todo-add"></use> - </svg> - - </div> - <h2>todo-add</h2> - </li> - <li title="todo-done"> - <div class="icon-box"> - - <!-- todo-done --> - <svg class="svg-todo-done-dims"> - <use xlink:href="#todo-done"></use> - </svg> - - </div> - <h2>todo-done</h2> - </li> - <li title="token"> - <div class="icon-box"> - - <!-- token --> - <svg class="svg-token-dims"> - <use xlink:href="#token"></use> - </svg> - - </div> - <h2>token</h2> - </li> - <li title="unapproval"> - <div class="icon-box"> - - <!-- unapproval --> - <svg class="svg-unapproval-dims"> - <use xlink:href="#unapproval"></use> - </svg> - - </div> - <h2>unapproval</h2> - </li> - <li title="unassignee"> - <div class="icon-box"> - - <!-- unassignee --> - <svg class="svg-unassignee-dims"> - <use xlink:href="#unassignee"></use> - </svg> - - </div> - <h2>unassignee</h2> - </li> - <li title="unlink"> - <div class="icon-box"> - - <!-- unlink --> - <svg class="svg-unlink-dims"> - <use xlink:href="#unlink"></use> - </svg> - - </div> - <h2>unlink</h2> - </li> - <li title="user"> - <div class="icon-box"> - - <!-- user --> - <svg class="svg-user-dims"> - <use xlink:href="#user"></use> - </svg> - - </div> - <h2>user</h2> - </li> - <li title="users"> - <div class="icon-box"> - - <!-- users --> - <svg class="svg-users-dims"> - <use xlink:href="#users"></use> - </svg> - - </div> - <h2>users</h2> - </li> - <li title="volume-up"> - <div class="icon-box"> - - <!-- volume-up --> - <svg class="svg-volume-up-dims"> - <use xlink:href="#volume-up"></use> - </svg> - - </div> - <h2>volume-up</h2> - </li> - <li title="warning"> - <div class="icon-box"> - - <!-- warning --> - <svg class="svg-warning-dims"> - <use xlink:href="#warning"></use> - </svg> - - </div> - <h2>warning</h2> - </li> - <li title="work"> - <div class="icon-box"> - - <!-- work --> - <svg class="svg-work-dims"> - <use xlink:href="#work"></use> - </svg> - - </div> - <h2>work</h2> - </li> - </ul> - -<!-- -==================================================================================================== ---> - - </section> - <section> - -<!-- - -B) Inline SVG with external sprite (IE 9-11 with polyfill only) -==================================================================================================== -These SVG images make use of an URL + fragment identifiers (IDs) and refer to the regular external -SVG sprite. They may be styled via CSS. (IE 9-11 with polyfill only) - ---> - - <h3>B) Inline SVG with external sprite (IE 9-11 with polyfill only)</h3> - <ul> - - <li title="abuse"> - <div class="icon-box"> - - <!-- abuse --> - <svg class="svg-abuse-dims"> - <use xlink:href="icons.svg#abuse"></use> - </svg> - - </div> - <h2>abuse</h2> - </li> - <li title="account"> - <div class="icon-box"> - - <!-- account --> - <svg class="svg-account-dims"> - <use xlink:href="icons.svg#account"></use> - </svg> - - </div> - <h2>account</h2> - </li> - <li title="admin"> - <div class="icon-box"> - - <!-- admin --> - <svg class="svg-admin-dims"> - <use xlink:href="icons.svg#admin"></use> - </svg> - - </div> - <h2>admin</h2> - </li> - <li title="angle-double-left"> - <div class="icon-box"> - - <!-- angle-double-left --> - <svg class="svg-angle-double-left-dims"> - <use xlink:href="icons.svg#angle-double-left"></use> - </svg> - - </div> - <h2>angle-double-left</h2> - </li> - <li title="angle-down"> - <div class="icon-box"> - - <!-- angle-down --> - <svg class="svg-angle-down-dims"> - <use xlink:href="icons.svg#angle-down"></use> - </svg> - - </div> - <h2>angle-down</h2> - </li> - <li title="angle-left"> - <div class="icon-box"> - - <!-- angle-left --> - <svg class="svg-angle-left-dims"> - <use xlink:href="icons.svg#angle-left"></use> - </svg> - - </div> - <h2>angle-left</h2> - </li> - <li title="angle-right"> - <div class="icon-box"> - - <!-- angle-right --> - <svg class="svg-angle-right-dims"> - <use xlink:href="icons.svg#angle-right"></use> - </svg> - - </div> - <h2>angle-right</h2> - </li> - <li title="angle-up"> - <div class="icon-box"> - - <!-- angle-up --> - <svg class="svg-angle-up-dims"> - <use xlink:href="icons.svg#angle-up"></use> - </svg> - - </div> - <h2>angle-up</h2> - </li> - <li title="appearance"> - <div class="icon-box"> - - <!-- appearance --> - <svg class="svg-appearance-dims"> - <use xlink:href="icons.svg#appearance"></use> - </svg> - - </div> - <h2>appearance</h2> - </li> - <li title="applications"> - <div class="icon-box"> - - <!-- applications --> - <svg class="svg-applications-dims"> - <use xlink:href="icons.svg#applications"></use> - </svg> - - </div> - <h2>applications</h2> - </li> - <li title="approval"> - <div class="icon-box"> - - <!-- approval --> - <svg class="svg-approval-dims"> - <use xlink:href="icons.svg#approval"></use> - </svg> - - </div> - <h2>approval</h2> - </li> - <li title="arrow-right"> - <div class="icon-box"> - - <!-- arrow-right --> - <svg class="svg-arrow-right-dims"> - <use xlink:href="icons.svg#arrow-right"></use> - </svg> - - </div> - <h2>arrow-right</h2> - </li> - <li title="assignee"> - <div class="icon-box"> - - <!-- assignee --> - <svg class="svg-assignee-dims"> - <use xlink:href="icons.svg#assignee"></use> - </svg> - - </div> - <h2>assignee</h2> - </li> - <li title="bold"> - <div class="icon-box"> - - <!-- bold --> - <svg class="svg-bold-dims"> - <use xlink:href="icons.svg#bold"></use> - </svg> - - </div> - <h2>bold</h2> - </li> - <li title="book"> - <div class="icon-box"> - - <!-- book --> - <svg class="svg-book-dims"> - <use xlink:href="icons.svg#book"></use> - </svg> - - </div> - <h2>book</h2> - </li> - <li title="branch"> - <div class="icon-box"> - - <!-- branch --> - <svg class="svg-branch-dims"> - <use xlink:href="icons.svg#branch"></use> - </svg> - - </div> - <h2>branch</h2> - </li> - <li title="calendar"> - <div class="icon-box"> - - <!-- calendar --> - <svg class="svg-calendar-dims"> - <use xlink:href="icons.svg#calendar"></use> - </svg> - - </div> - <h2>calendar</h2> - </li> - <li title="cancel"> - <div class="icon-box"> - - <!-- cancel --> - <svg class="svg-cancel-dims"> - <use xlink:href="icons.svg#cancel"></use> - </svg> - - </div> - <h2>cancel</h2> - </li> - <li title="chevron-down"> - <div class="icon-box"> - - <!-- chevron-down --> - <svg class="svg-chevron-down-dims"> - <use xlink:href="icons.svg#chevron-down"></use> - </svg> - - </div> - <h2>chevron-down</h2> - </li> - <li title="chevron-left"> - <div class="icon-box"> - - <!-- chevron-left --> - <svg class="svg-chevron-left-dims"> - <use xlink:href="icons.svg#chevron-left"></use> - </svg> - - </div> - <h2>chevron-left</h2> - </li> - <li title="chevron-right"> - <div class="icon-box"> - - <!-- chevron-right --> - <svg class="svg-chevron-right-dims"> - <use xlink:href="icons.svg#chevron-right"></use> - </svg> - - </div> - <h2>chevron-right</h2> - </li> - <li title="chevron-up"> - <div class="icon-box"> - - <!-- chevron-up --> - <svg class="svg-chevron-up-dims"> - <use xlink:href="icons.svg#chevron-up"></use> - </svg> - - </div> - <h2>chevron-up</h2> - </li> - <li title="clock"> - <div class="icon-box"> - - <!-- clock --> - <svg class="svg-clock-dims"> - <use xlink:href="icons.svg#clock"></use> - </svg> - - </div> - <h2>clock</h2> - </li> - <li title="code"> - <div class="icon-box"> - - <!-- code --> - <svg class="svg-code-dims"> - <use xlink:href="icons.svg#code"></use> - </svg> - - </div> - <h2>code</h2> - </li> - <li title="comment"> - <div class="icon-box"> - - <!-- comment --> - <svg class="svg-comment-dims"> - <use xlink:href="icons.svg#comment"></use> - </svg> - - </div> - <h2>comment</h2> - </li> - <li title="comment-dots"> - <div class="icon-box"> - - <!-- comment-dots --> - <svg class="svg-comment-dots-dims"> - <use xlink:href="icons.svg#comment-dots"></use> - </svg> - - </div> - <h2>comment-dots</h2> - </li> - <li title="comment-next"> - <div class="icon-box"> - - <!-- comment-next --> - <svg class="svg-comment-next-dims"> - <use xlink:href="icons.svg#comment-next"></use> - </svg> - - </div> - <h2>comment-next</h2> - </li> - <li title="comments"> - <div class="icon-box"> - - <!-- comments --> - <svg class="svg-comments-dims"> - <use xlink:href="icons.svg#comments"></use> - </svg> - - </div> - <h2>comments</h2> - </li> - <li title="commit"> - <div class="icon-box"> - - <!-- commit --> - <svg class="svg-commit-dims"> - <use xlink:href="icons.svg#commit"></use> - </svg> - - </div> - <h2>commit</h2> - </li> - <li title="credit-card"> - <div class="icon-box"> - - <!-- credit-card --> - <svg class="svg-credit-card-dims"> - <use xlink:href="icons.svg#credit-card"></use> - </svg> - - </div> - <h2>credit-card</h2> - </li> - <li title="disk"> - <div class="icon-box"> - - <!-- disk --> - <svg class="svg-disk-dims"> - <use xlink:href="icons.svg#disk"></use> - </svg> - - </div> - <h2>disk</h2> - </li> - <li title="doc_code"> - <div class="icon-box"> - - <!-- doc_code --> - <svg class="svg-doc_code-dims"> - <use xlink:href="icons.svg#doc_code"></use> - </svg> - - </div> - <h2>doc_code</h2> - </li> - <li title="doc_image"> - <div class="icon-box"> - - <!-- doc_image --> - <svg class="svg-doc_image-dims"> - <use xlink:href="icons.svg#doc_image"></use> - </svg> - - </div> - <h2>doc_image</h2> - </li> - <li title="doc_text"> - <div class="icon-box"> - - <!-- doc_text --> - <svg class="svg-doc_text-dims"> - <use xlink:href="icons.svg#doc_text"></use> - </svg> - - </div> - <h2>doc_text</h2> - </li> - <li title="download"> - <div class="icon-box"> - - <!-- download --> - <svg class="svg-download-dims"> - <use xlink:href="icons.svg#download"></use> - </svg> - - </div> - <h2>download</h2> - </li> - <li title="duplicate"> - <div class="icon-box"> - - <!-- duplicate --> - <svg class="svg-duplicate-dims"> - <use xlink:href="icons.svg#duplicate"></use> - </svg> - - </div> - <h2>duplicate</h2> - </li> - <li title="earth"> - <div class="icon-box"> - - <!-- earth --> - <svg class="svg-earth-dims"> - <use xlink:href="icons.svg#earth"></use> - </svg> - - </div> - <h2>earth</h2> - </li> - <li title="eye"> - <div class="icon-box"> - - <!-- eye --> - <svg class="svg-eye-dims"> - <use xlink:href="icons.svg#eye"></use> - </svg> - - </div> - <h2>eye</h2> - </li> - <li title="eye-slash"> - <div class="icon-box"> - - <!-- eye-slash --> - <svg class="svg-eye-slash-dims"> - <use xlink:href="icons.svg#eye-slash"></use> - </svg> - - </div> - <h2>eye-slash</h2> - </li> - <li title="file-additions"> - <div class="icon-box"> - - <!-- file-additions --> - <svg class="svg-file-additions-dims"> - <use xlink:href="icons.svg#file-additions"></use> - </svg> - - </div> - <h2>file-additions</h2> - </li> - <li title="file-deletion"> - <div class="icon-box"> - - <!-- file-deletion --> - <svg class="svg-file-deletion-dims"> - <use xlink:href="icons.svg#file-deletion"></use> - </svg> - - </div> - <h2>file-deletion</h2> - </li> - <li title="file-modified"> - <div class="icon-box"> - - <!-- file-modified --> - <svg class="svg-file-modified-dims"> - <use xlink:href="icons.svg#file-modified"></use> - </svg> - - </div> - <h2>file-modified</h2> - </li> - <li title="filter"> - <div class="icon-box"> - - <!-- filter --> - <svg class="svg-filter-dims"> - <use xlink:href="icons.svg#filter"></use> - </svg> - - </div> - <h2>filter</h2> - </li> - <li title="folder"> - <div class="icon-box"> - - <!-- folder --> - <svg class="svg-folder-dims"> - <use xlink:href="icons.svg#folder"></use> - </svg> - - </div> - <h2>folder</h2> - </li> - <li title="fork"> - <div class="icon-box"> - - <!-- fork --> - <svg class="svg-fork-dims"> - <use xlink:href="icons.svg#fork"></use> - </svg> - - </div> - <h2>fork</h2> - </li> - <li title="git-merge"> - <div class="icon-box"> - - <!-- git-merge --> - <svg class="svg-git-merge-dims"> - <use xlink:href="icons.svg#git-merge"></use> - </svg> - - </div> - <h2>git-merge</h2> - </li> - <li title="group"> - <div class="icon-box"> - - <!-- group --> - <svg class="svg-group-dims"> - <use xlink:href="icons.svg#group"></use> - </svg> - - </div> - <h2>group</h2> - </li> - <li title="history"> - <div class="icon-box"> - - <!-- history --> - <svg class="svg-history-dims"> - <use xlink:href="icons.svg#history"></use> - </svg> - - </div> - <h2>history</h2> - </li> - <li title="home"> - <div class="icon-box"> - - <!-- home --> - <svg class="svg-home-dims"> - <use xlink:href="icons.svg#home"></use> - </svg> - - </div> - <h2>home</h2> - </li> - <li title="hook"> - <div class="icon-box"> - - <!-- hook --> - <svg class="svg-hook-dims"> - <use xlink:href="icons.svg#hook"></use> - </svg> - - </div> - <h2>hook</h2> - </li> - <li title="issue-block"> - <div class="icon-box"> - - <!-- issue-block --> - <svg class="svg-issue-block-dims"> - <use xlink:href="icons.svg#issue-block"></use> - </svg> - - </div> - <h2>issue-block</h2> - </li> - <li title="issue-child"> - <div class="icon-box"> - - <!-- issue-child --> - <svg class="svg-issue-child-dims"> - <use xlink:href="icons.svg#issue-child"></use> - </svg> - - </div> - <h2>issue-child</h2> - </li> - <li title="issue-close"> - <div class="icon-box"> - - <!-- issue-close --> - <svg class="svg-issue-close-dims"> - <use xlink:href="icons.svg#issue-close"></use> - </svg> - - </div> - <h2>issue-close</h2> - </li> - <li title="issue-duplicate"> - <div class="icon-box"> - - <!-- issue-duplicate --> - <svg class="svg-issue-duplicate-dims"> - <use xlink:href="icons.svg#issue-duplicate"></use> - </svg> - - </div> - <h2>issue-duplicate</h2> - </li> - <li title="issue-new"> - <div class="icon-box"> - - <!-- issue-new --> - <svg class="svg-issue-new-dims"> - <use xlink:href="icons.svg#issue-new"></use> - </svg> - - </div> - <h2>issue-new</h2> - </li> - <li title="issue-open"> - <div class="icon-box"> - - <!-- issue-open --> - <svg class="svg-issue-open-dims"> - <use xlink:href="icons.svg#issue-open"></use> - </svg> - - </div> - <h2>issue-open</h2> - </li> - <li title="issue-open-m"> - <div class="icon-box"> - - <!-- issue-open-m --> - <svg class="svg-issue-open-m-dims"> - <use xlink:href="icons.svg#issue-open-m"></use> - </svg> - - </div> - <h2>issue-open-m</h2> - </li> - <li title="issue-parent"> - <div class="icon-box"> - - <!-- issue-parent --> - <svg class="svg-issue-parent-dims"> - <use xlink:href="icons.svg#issue-parent"></use> - </svg> - - </div> - <h2>issue-parent</h2> - </li> - <li title="issues"> - <div class="icon-box"> - - <!-- issues --> - <svg class="svg-issues-dims"> - <use xlink:href="icons.svg#issues"></use> - </svg> - - </div> - <h2>issues</h2> - </li> - <li title="key"> - <div class="icon-box"> - - <!-- key --> - <svg class="svg-key-dims"> - <use xlink:href="icons.svg#key"></use> - </svg> - - </div> - <h2>key</h2> - </li> - <li title="key-2"> - <div class="icon-box"> - - <!-- key-2 --> - <svg class="svg-key-2-dims"> - <use xlink:href="icons.svg#key-2"></use> - </svg> - - </div> - <h2>key-2</h2> - </li> - <li title="label"> - <div class="icon-box"> - - <!-- label --> - <svg class="svg-label-dims"> - <use xlink:href="icons.svg#label"></use> - </svg> - - </div> - <h2>label</h2> - </li> - <li title="labels"> - <div class="icon-box"> - - <!-- labels --> - <svg class="svg-labels-dims"> - <use xlink:href="icons.svg#labels"></use> - </svg> - - </div> - <h2>labels</h2> - </li> - <li title="leave"> - <div class="icon-box"> - - <!-- leave --> - <svg class="svg-leave-dims"> - <use xlink:href="icons.svg#leave"></use> - </svg> - - </div> - <h2>leave</h2> - </li> - <li title="level-up"> - <div class="icon-box"> - - <!-- level-up --> - <svg class="svg-level-up-dims"> - <use xlink:href="icons.svg#level-up"></use> - </svg> - - </div> - <h2>level-up</h2> - </li> - <li title="license"> - <div class="icon-box"> - - <!-- license --> - <svg class="svg-license-dims"> - <use xlink:href="icons.svg#license"></use> - </svg> - - </div> - <h2>license</h2> - </li> - <li title="link"> - <div class="icon-box"> - - <!-- link --> - <svg class="svg-link-dims"> - <use xlink:href="icons.svg#link"></use> - </svg> - - </div> - <h2>link</h2> - </li> - <li title="list-bulleted"> - <div class="icon-box"> - - <!-- list-bulleted --> - <svg class="svg-list-bulleted-dims"> - <use xlink:href="icons.svg#list-bulleted"></use> - </svg> - - </div> - <h2>list-bulleted</h2> - </li> - <li title="list-numbered"> - <div class="icon-box"> - - <!-- list-numbered --> - <svg class="svg-list-numbered-dims"> - <use xlink:href="icons.svg#list-numbered"></use> - </svg> - - </div> - <h2>list-numbered</h2> - </li> - <li title="location"> - <div class="icon-box"> - - <!-- location --> - <svg class="svg-location-dims"> - <use xlink:href="icons.svg#location"></use> - </svg> - - </div> - <h2>location</h2> - </li> - <li title="location-dot"> - <div class="icon-box"> - - <!-- location-dot --> - <svg class="svg-location-dot-dims"> - <use xlink:href="icons.svg#location-dot"></use> - </svg> - - </div> - <h2>location-dot</h2> - </li> - <li title="lock"> - <div class="icon-box"> - - <!-- lock --> - <svg class="svg-lock-dims"> - <use xlink:href="icons.svg#lock"></use> - </svg> - - </div> - <h2>lock</h2> - </li> - <li title="lock-open"> - <div class="icon-box"> - - <!-- lock-open --> - <svg class="svg-lock-open-dims"> - <use xlink:href="icons.svg#lock-open"></use> - </svg> - - </div> - <h2>lock-open</h2> - </li> - <li title="log"> - <div class="icon-box"> - - <!-- log --> - <svg class="svg-log-dims"> - <use xlink:href="icons.svg#log"></use> - </svg> - - </div> - <h2>log</h2> - </li> - <li title="mail"> - <div class="icon-box"> - - <!-- mail --> - <svg class="svg-mail-dims"> - <use xlink:href="icons.svg#mail"></use> - </svg> - - </div> - <h2>mail</h2> - </li> - <li title="merge-request-close"> - <div class="icon-box"> - - <!-- merge-request-close --> - <svg class="svg-merge-request-close-dims"> - <use xlink:href="icons.svg#merge-request-close"></use> - </svg> - - </div> - <h2>merge-request-close</h2> - </li> - <li title="merge-request-close-m"> - <div class="icon-box"> - - <!-- merge-request-close-m --> - <svg class="svg-merge-request-close-m-dims"> - <use xlink:href="icons.svg#merge-request-close-m"></use> - </svg> - - </div> - <h2>merge-request-close-m</h2> - </li> - <li title="messages"> - <div class="icon-box"> - - <!-- messages --> - <svg class="svg-messages-dims"> - <use xlink:href="icons.svg#messages"></use> - </svg> - - </div> - <h2>messages</h2> - </li> - <li title="mobile-issue-close"> - <div class="icon-box"> - - <!-- mobile-issue-close --> - <svg class="svg-mobile-issue-close-dims"> - <use xlink:href="icons.svg#mobile-issue-close"></use> - </svg> - - </div> - <h2>mobile-issue-close</h2> - </li> - <li title="monitor"> - <div class="icon-box"> - - <!-- monitor --> - <svg class="svg-monitor-dims"> - <use xlink:href="icons.svg#monitor"></use> - </svg> - - </div> - <h2>monitor</h2> - </li> - <li title="more"> - <div class="icon-box"> - - <!-- more --> - <svg class="svg-more-dims"> - <use xlink:href="icons.svg#more"></use> - </svg> - - </div> - <h2>more</h2> - </li> - <li title="notifications"> - <div class="icon-box"> - - <!-- notifications --> - <svg class="svg-notifications-dims"> - <use xlink:href="icons.svg#notifications"></use> - </svg> - - </div> - <h2>notifications</h2> - </li> - <li title="notifications-off"> - <div class="icon-box"> - - <!-- notifications-off --> - <svg class="svg-notifications-off-dims"> - <use xlink:href="icons.svg#notifications-off"></use> - </svg> - - </div> - <h2>notifications-off</h2> - </li> - <li title="overview"> - <div class="icon-box"> - - <!-- overview --> - <svg class="svg-overview-dims"> - <use xlink:href="icons.svg#overview"></use> - </svg> - - </div> - <h2>overview</h2> - </li> - <li title="pencil"> - <div class="icon-box"> - - <!-- pencil --> - <svg class="svg-pencil-dims"> - <use xlink:href="icons.svg#pencil"></use> - </svg> - - </div> - <h2>pencil</h2> - </li> - <li title="pipeline"> - <div class="icon-box"> - - <!-- pipeline --> - <svg class="svg-pipeline-dims"> - <use xlink:href="icons.svg#pipeline"></use> - </svg> - - </div> - <h2>pipeline</h2> - </li> - <li title="play"> - <div class="icon-box"> - - <!-- play --> - <svg class="svg-play-dims"> - <use xlink:href="icons.svg#play"></use> - </svg> - - </div> - <h2>play</h2> - </li> - <li title="plus"> - <div class="icon-box"> - - <!-- plus --> - <svg class="svg-plus-dims"> - <use xlink:href="icons.svg#plus"></use> - </svg> - - </div> - <h2>plus</h2> - </li> - <li title="plus-square"> - <div class="icon-box"> - - <!-- plus-square --> - <svg class="svg-plus-square-dims"> - <use xlink:href="icons.svg#plus-square"></use> - </svg> - - </div> - <h2>plus-square</h2> - </li> - <li title="plus-square-o"> - <div class="icon-box"> - - <!-- plus-square-o --> - <svg class="svg-plus-square-o-dims"> - <use xlink:href="icons.svg#plus-square-o"></use> - </svg> - - </div> - <h2>plus-square-o</h2> - </li> - <li title="preferences"> - <div class="icon-box"> - - <!-- preferences --> - <svg class="svg-preferences-dims"> - <use xlink:href="icons.svg#preferences"></use> - </svg> - - </div> - <h2>preferences</h2> - </li> - <li title="profile"> - <div class="icon-box"> - - <!-- profile --> - <svg class="svg-profile-dims"> - <use xlink:href="icons.svg#profile"></use> - </svg> - - </div> - <h2>profile</h2> - </li> - <li title="project"> - <div class="icon-box"> - - <!-- project --> - <svg class="svg-project-dims"> - <use xlink:href="icons.svg#project"></use> - </svg> - - </div> - <h2>project</h2> - </li> - <li title="push-rules"> - <div class="icon-box"> - - <!-- push-rules --> - <svg class="svg-push-rules-dims"> - <use xlink:href="icons.svg#push-rules"></use> - </svg> - - </div> - <h2>push-rules</h2> - </li> - <li title="question"> - <div class="icon-box"> - - <!-- question --> - <svg class="svg-question-dims"> - <use xlink:href="icons.svg#question"></use> - </svg> - - </div> - <h2>question</h2> - </li> - <li title="question-o"> - <div class="icon-box"> - - <!-- question-o --> - <svg class="svg-question-o-dims"> - <use xlink:href="icons.svg#question-o"></use> - </svg> - - </div> - <h2>question-o</h2> - </li> - <li title="quote"> - <div class="icon-box"> - - <!-- quote --> - <svg class="svg-quote-dims"> - <use xlink:href="icons.svg#quote"></use> - </svg> - - </div> - <h2>quote</h2> - </li> - <li title="redo"> - <div class="icon-box"> - - <!-- redo --> - <svg class="svg-redo-dims"> - <use xlink:href="icons.svg#redo"></use> - </svg> - - </div> - <h2>redo</h2> - </li> - <li title="remove"> - <div class="icon-box"> - - <!-- remove --> - <svg class="svg-remove-dims"> - <use xlink:href="icons.svg#remove"></use> - </svg> - - </div> - <h2>remove</h2> - </li> - <li title="repeat"> - <div class="icon-box"> - - <!-- repeat --> - <svg class="svg-repeat-dims"> - <use xlink:href="icons.svg#repeat"></use> - </svg> - - </div> - <h2>repeat</h2> - </li> - <li title="retry"> - <div class="icon-box"> - - <!-- retry --> - <svg class="svg-retry-dims"> - <use xlink:href="icons.svg#retry"></use> - </svg> - - </div> - <h2>retry</h2> - </li> - <li title="scale"> - <div class="icon-box"> - - <!-- scale --> - <svg class="svg-scale-dims"> - <use xlink:href="icons.svg#scale"></use> - </svg> - - </div> - <h2>scale</h2> - </li> - <li title="screen-full"> - <div class="icon-box"> - - <!-- screen-full --> - <svg class="svg-screen-full-dims"> - <use xlink:href="icons.svg#screen-full"></use> - </svg> - - </div> - <h2>screen-full</h2> - </li> - <li title="screen-normal"> - <div class="icon-box"> - - <!-- screen-normal --> - <svg class="svg-screen-normal-dims"> - <use xlink:href="icons.svg#screen-normal"></use> - </svg> - - </div> - <h2>screen-normal</h2> - </li> - <li title="search"> - <div class="icon-box"> - - <!-- search --> - <svg class="svg-search-dims"> - <use xlink:href="icons.svg#search"></use> - </svg> - - </div> - <h2>search</h2> - </li> - <li title="settings"> - <div class="icon-box"> - - <!-- settings --> - <svg class="svg-settings-dims"> - <use xlink:href="icons.svg#settings"></use> - </svg> - - </div> - <h2>settings</h2> - </li> - <li title="shield"> - <div class="icon-box"> - - <!-- shield --> - <svg class="svg-shield-dims"> - <use xlink:href="icons.svg#shield"></use> - </svg> - - </div> - <h2>shield</h2> - </li> - <li title="slight-frown"> - <div class="icon-box"> - - <!-- slight-frown --> - <svg class="svg-slight-frown-dims"> - <use xlink:href="icons.svg#slight-frown"></use> - </svg> - - </div> - <h2>slight-frown</h2> - </li> - <li title="slight-smile"> - <div class="icon-box"> - - <!-- slight-smile --> - <svg class="svg-slight-smile-dims"> - <use xlink:href="icons.svg#slight-smile"></use> - </svg> - - </div> - <h2>slight-smile</h2> - </li> - <li title="smile"> - <div class="icon-box"> - - <!-- smile --> - <svg class="svg-smile-dims"> - <use xlink:href="icons.svg#smile"></use> - </svg> - - </div> - <h2>smile</h2> - </li> - <li title="smiley"> - <div class="icon-box"> - - <!-- smiley --> - <svg class="svg-smiley-dims"> - <use xlink:href="icons.svg#smiley"></use> - </svg> - - </div> - <h2>smiley</h2> - </li> - <li title="snippet"> - <div class="icon-box"> - - <!-- snippet --> - <svg class="svg-snippet-dims"> - <use xlink:href="icons.svg#snippet"></use> - </svg> - - </div> - <h2>snippet</h2> - </li> - <li title="spam"> - <div class="icon-box"> - - <!-- spam --> - <svg class="svg-spam-dims"> - <use xlink:href="icons.svg#spam"></use> - </svg> - - </div> - <h2>spam</h2> - </li> - <li title="star"> - <div class="icon-box"> - - <!-- star --> - <svg class="svg-star-dims"> - <use xlink:href="icons.svg#star"></use> - </svg> - - </div> - <h2>star</h2> - </li> - <li title="star-o"> - <div class="icon-box"> - - <!-- star-o --> - <svg class="svg-star-o-dims"> - <use xlink:href="icons.svg#star-o"></use> - </svg> - - </div> - <h2>star-o</h2> - </li> - <li title="stop"> - <div class="icon-box"> - - <!-- stop --> - <svg class="svg-stop-dims"> - <use xlink:href="icons.svg#stop"></use> - </svg> - - </div> - <h2>stop</h2> - </li> - <li title="talic"> - <div class="icon-box"> - - <!-- talic --> - <svg class="svg-talic-dims"> - <use xlink:href="icons.svg#talic"></use> - </svg> - - </div> - <h2>talic</h2> - </li> - <li title="task-done"> - <div class="icon-box"> - - <!-- task-done --> - <svg class="svg-task-done-dims"> - <use xlink:href="icons.svg#task-done"></use> - </svg> - - </div> - <h2>task-done</h2> - </li> - <li title="template"> - <div class="icon-box"> - - <!-- template --> - <svg class="svg-template-dims"> - <use xlink:href="icons.svg#template"></use> - </svg> - - </div> - <h2>template</h2> - </li> - <li title="thump-down"> - <div class="icon-box"> - - <!-- thump-down --> - <svg class="svg-thump-down-dims"> - <use xlink:href="icons.svg#thump-down"></use> - </svg> - - </div> - <h2>thump-down</h2> - </li> - <li title="thump-up"> - <div class="icon-box"> - - <!-- thump-up --> - <svg class="svg-thump-up-dims"> - <use xlink:href="icons.svg#thump-up"></use> - </svg> - - </div> - <h2>thump-up</h2> - </li> - <li title="timer"> - <div class="icon-box"> - - <!-- timer --> - <svg class="svg-timer-dims"> - <use xlink:href="icons.svg#timer"></use> - </svg> - - </div> - <h2>timer</h2> - </li> - <li title="todo-add"> - <div class="icon-box"> - - <!-- todo-add --> - <svg class="svg-todo-add-dims"> - <use xlink:href="icons.svg#todo-add"></use> - </svg> - - </div> - <h2>todo-add</h2> - </li> - <li title="todo-done"> - <div class="icon-box"> - - <!-- todo-done --> - <svg class="svg-todo-done-dims"> - <use xlink:href="icons.svg#todo-done"></use> - </svg> - - </div> - <h2>todo-done</h2> - </li> - <li title="token"> - <div class="icon-box"> - - <!-- token --> - <svg class="svg-token-dims"> - <use xlink:href="icons.svg#token"></use> - </svg> - - </div> - <h2>token</h2> - </li> - <li title="unapproval"> - <div class="icon-box"> - - <!-- unapproval --> - <svg class="svg-unapproval-dims"> - <use xlink:href="icons.svg#unapproval"></use> - </svg> - - </div> - <h2>unapproval</h2> - </li> - <li title="unassignee"> - <div class="icon-box"> - - <!-- unassignee --> - <svg class="svg-unassignee-dims"> - <use xlink:href="icons.svg#unassignee"></use> - </svg> - - </div> - <h2>unassignee</h2> - </li> - <li title="unlink"> - <div class="icon-box"> - - <!-- unlink --> - <svg class="svg-unlink-dims"> - <use xlink:href="icons.svg#unlink"></use> - </svg> - - </div> - <h2>unlink</h2> - </li> - <li title="user"> - <div class="icon-box"> - - <!-- user --> - <svg class="svg-user-dims"> - <use xlink:href="icons.svg#user"></use> - </svg> - - </div> - <h2>user</h2> - </li> - <li title="users"> - <div class="icon-box"> - - <!-- users --> - <svg class="svg-users-dims"> - <use xlink:href="icons.svg#users"></use> - </svg> - - </div> - <h2>users</h2> - </li> - <li title="volume-up"> - <div class="icon-box"> - - <!-- volume-up --> - <svg class="svg-volume-up-dims"> - <use xlink:href="icons.svg#volume-up"></use> - </svg> - - </div> - <h2>volume-up</h2> - </li> - <li title="warning"> - <div class="icon-box"> - - <!-- warning --> - <svg class="svg-warning-dims"> - <use xlink:href="icons.svg#warning"></use> - </svg> - - </div> - <h2>warning</h2> - </li> - <li title="work"> - <div class="icon-box"> - - <!-- work --> - <svg class="svg-work-dims"> - <use xlink:href="icons.svg#work"></use> - </svg> - - </div> - <h2>work</h2> - </li> - </ul> - -<!-- -==================================================================================================== ---> - - </section> - <footer> - <p>Generated at Tue, 12 Sep 2017 09:08:46 GMT by <a href="https://github.com/jkphl/svg-sprite" target="_blank">svg-sprite</a>.</p> - </footer> - </body> -</html> diff --git a/app/assets/javascripts/blob/notebook/index.js b/app/assets/javascripts/blob/notebook/index.js index 27312d718b0..c858a6bb7b4 100644 --- a/app/assets/javascripts/blob/notebook/index.js +++ b/app/assets/javascripts/blob/notebook/index.js @@ -40,10 +40,10 @@ export default () => { class="text-center" v-if="error"> <span v-if="loadError"> - An error occured whilst loading the file. Please try again later. + An error occurred whilst loading the file. Please try again later. </span> <span v-else> - An error occured whilst parsing the file. + An error occurred whilst parsing the file. </span> </p> </div> diff --git a/app/assets/javascripts/blob/pdf/index.js b/app/assets/javascripts/blob/pdf/index.js index 0ed915c1ac9..7109f356540 100644 --- a/app/assets/javascripts/blob/pdf/index.js +++ b/app/assets/javascripts/blob/pdf/index.js @@ -48,10 +48,10 @@ export default () => { class="text-center" v-if="error"> <span v-if="loadError"> - An error occured whilst loading the file. Please try again later. + An error occurred whilst loading the file. Please try again later. </span> <span v-else> - An error occured whilst decoding the file. + An error occurred whilst decoding the file. </span> </p> </div> diff --git a/app/assets/javascripts/boards/boards_bundle.js b/app/assets/javascripts/boards/boards_bundle.js index ea00efe4b46..815248f38ee 100644 --- a/app/assets/javascripts/boards/boards_bundle.js +++ b/app/assets/javascripts/boards/boards_bundle.js @@ -77,9 +77,6 @@ $(() => { }); Store.rootPath = this.boardsEndpoint; - this.filterManager = new FilteredSearchBoards(Store.filter, true); - this.filterManager.setup(); - // Listen for updateTokens event eventHub.$on('updateTokens', this.updateTokens); }, @@ -87,6 +84,9 @@ $(() => { eventHub.$off('updateTokens', this.updateTokens); }, mounted () { + this.filterManager = new FilteredSearchBoards(Store.filter, true); + this.filterManager.setup(); + Store.disabled = this.disabled; gl.boardService.all() .then(response => response.json()) diff --git a/app/assets/javascripts/boards/components/board_new_issue.js b/app/assets/javascripts/boards/components/board_new_issue.js index 541b8049855..bc28f7f45f4 100644 --- a/app/assets/javascripts/boards/components/board_new_issue.js +++ b/app/assets/javascripts/boards/components/board_new_issue.js @@ -68,7 +68,7 @@ export default { <div class="flash-container" v-if="error"> <div class="flash-alert"> - An error occured. Please try again. + An error occurred. Please try again. </div> </div> <label class="label-light" diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index 286a758b8a9..3d27a3544eb 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -167,7 +167,7 @@ window.Build = (function () { Build.prototype.getBuildTrace = function () { return $.ajax({ url: `${this.pageUrl}/trace.json`, - data: this.state, + data: { state: this.state }, }) .done((log) => { setCiStatusFavicon(`${this.pageUrl}/status.json`); diff --git a/app/assets/javascripts/copy_as_gfm.js b/app/assets/javascripts/copy_as_gfm.js index e3e2c798570..93b0cbf4209 100644 --- a/app/assets/javascripts/copy_as_gfm.js +++ b/app/assets/javascripts/copy_as_gfm.js @@ -298,7 +298,7 @@ class CopyAsGFM { const documentFragment = getSelectedFragment(); if (!documentFragment) return; - const el = transformer(documentFragment.cloneNode(true)); + const el = transformer(documentFragment.cloneNode(true), e.currentTarget); if (!el) return; e.preventDefault(); @@ -338,55 +338,64 @@ class CopyAsGFM { } static transformGFMSelection(documentFragment) { - const gfmEls = documentFragment.querySelectorAll('.md, .wiki'); - switch (gfmEls.length) { + const gfmElements = documentFragment.querySelectorAll('.md, .wiki'); + switch (gfmElements.length) { case 0: { return documentFragment; } case 1: { - return gfmEls[0]; + return gfmElements[0]; } default: { - const allGfmEl = document.createElement('div'); + const allGfmElement = document.createElement('div'); - for (let i = 0; i < gfmEls.length; i += 1) { - const lineEl = gfmEls[i]; - allGfmEl.appendChild(lineEl); - allGfmEl.appendChild(document.createTextNode('\n\n')); + for (let i = 0; i < gfmElements.length; i += 1) { + const gfmElement = gfmElements[i]; + allGfmElement.appendChild(gfmElement); + allGfmElement.appendChild(document.createTextNode('\n\n')); } - return allGfmEl; + return allGfmElement; } } } - static transformCodeSelection(documentFragment) { - const lineEls = documentFragment.querySelectorAll('.line'); + static transformCodeSelection(documentFragment, target) { + let lineSelector = '.line'; - let codeEl; - if (lineEls.length > 1) { - codeEl = document.createElement('pre'); - codeEl.className = 'code highlight'; + if (target) { + const lineClass = ['left-side', 'right-side'].filter(name => target.classList.contains(name))[0]; + if (lineClass) { + lineSelector = `.line_content.${lineClass} ${lineSelector}`; + } + } + + const lineElements = documentFragment.querySelectorAll(lineSelector); + + let codeElement; + if (lineElements.length > 1) { + codeElement = document.createElement('pre'); + codeElement.className = 'code highlight'; - const lang = lineEls[0].getAttribute('lang'); + const lang = lineElements[0].getAttribute('lang'); if (lang) { - codeEl.setAttribute('lang', lang); + codeElement.setAttribute('lang', lang); } } else { - codeEl = document.createElement('code'); + codeElement = document.createElement('code'); } - if (lineEls.length > 0) { - for (let i = 0; i < lineEls.length; i += 1) { - const lineEl = lineEls[i]; - codeEl.appendChild(lineEl); - codeEl.appendChild(document.createTextNode('\n')); + if (lineElements.length > 0) { + for (let i = 0; i < lineElements.length; i += 1) { + const lineElement = lineElements[i]; + codeElement.appendChild(lineElement); + codeElement.appendChild(document.createTextNode('\n')); } } else { - codeEl.appendChild(documentFragment); + codeElement.appendChild(documentFragment); } - return codeEl; + return codeElement; } static nodeToGFM(node, respectWhitespaceParam = false) { diff --git a/app/assets/javascripts/cycle_analytics/components/limit_warning_component.js b/app/assets/javascripts/cycle_analytics/components/limit_warning_component.js deleted file mode 100644 index 8d3d34f836f..00000000000 --- a/app/assets/javascripts/cycle_analytics/components/limit_warning_component.js +++ /dev/null @@ -1,17 +0,0 @@ -export default { - props: { - count: { - type: Number, - required: true, - }, - }, - template: ` - <span v-if="count === 50" class="events-info pull-right"> - <i class="fa fa-warning has-tooltip" - aria-hidden="true" - :title="n__('Limited to showing %d event at most', 'Limited to showing %d events at most', 50)" - data-placement="top"></i> - {{ n__('Showing %d event', 'Showing %d events', 50) }} - </span> - `, -}; diff --git a/app/assets/javascripts/cycle_analytics/components/limit_warning_component.vue b/app/assets/javascripts/cycle_analytics/components/limit_warning_component.vue new file mode 100644 index 00000000000..6e94ba929b2 --- /dev/null +++ b/app/assets/javascripts/cycle_analytics/components/limit_warning_component.vue @@ -0,0 +1,26 @@ +<script> + import tooltip from '../../vue_shared/directives/tooltip'; + + export default { + props: { + count: { + type: Number, + required: true, + }, + }, + directives: { + tooltip, + }, + }; +</script> +<template> + <span v-if="count === 50" class="events-info pull-right"> + <i + class="fa fa-warning" + v-tooltip + aria-hidden="true" + :title="n__('Limited to showing %d event at most', 'Limited to showing %d events at most', 50)" + data-placement="top"></i> + {{ n__('Showing %d event', 'Showing %d events', 50) }} + </span> +</template> diff --git a/app/assets/javascripts/cycle_analytics/components/stage_code_component.js b/app/assets/javascripts/cycle_analytics/components/stage_code_component.js deleted file mode 100644 index 7c32a38fbe7..00000000000 --- a/app/assets/javascripts/cycle_analytics/components/stage_code_component.js +++ /dev/null @@ -1,51 +0,0 @@ -/* eslint-disable no-param-reassign */ - -import Vue from 'vue'; -import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue'; - -const global = window.gl || (window.gl = {}); -global.cycleAnalytics = global.cycleAnalytics || {}; - -global.cycleAnalytics.StageCodeComponent = Vue.extend({ - props: { - items: Array, - stage: Object, - }, - components: { - userAvatarImage, - }, - template: ` - <div> - <div class="events-description"> - {{ stage.description }} - <limit-warning :count="items.length" /> - </div> - <ul class="stage-event-list"> - <li v-for="mergeRequest in items" class="stage-event-item"> - <div class="item-details"> - <!-- FIXME: Pass an alt attribute here for accessibility --> - <user-avatar-image :img-src="mergeRequest.author.avatarUrl"/> - <h5 class="item-title merge-merquest-title"> - <a :href="mergeRequest.url"> - {{ mergeRequest.title }} - </a> - </h5> - <a :href="mergeRequest.url" class="issue-link">!{{ mergeRequest.iid }}</a> - · - <span> - {{ s__('OpenedNDaysAgo|Opened') }} - <a :href="mergeRequest.url" class="issue-date">{{ mergeRequest.createdAt }}</a> - </span> - <span> - {{ s__('ByAuthor|by') }} - <a :href="mergeRequest.author.webUrl" class="issue-author-link">{{ mergeRequest.author.name }}</a> - </span> - </div> - <div class="item-time"> - <total-time :time="mergeRequest.totalTime"></total-time> - </div> - </li> - </ul> - </div> - `, -}); diff --git a/app/assets/javascripts/cycle_analytics/components/stage_code_component.vue b/app/assets/javascripts/cycle_analytics/components/stage_code_component.vue new file mode 100644 index 00000000000..45930145b0a --- /dev/null +++ b/app/assets/javascripts/cycle_analytics/components/stage_code_component.vue @@ -0,0 +1,51 @@ +<script> + import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue'; + import limitWarning from './limit_warning_component.vue'; + import totalTime from './total_time_component.vue'; + + export default { + props: { + items: Array, + stage: Object, + }, + components: { + userAvatarImage, + limitWarning, + totalTime, + }, + }; +</script> +<template> + <div> + <div class="events-description"> + {{ stage.description }} + <limit-warning :count="items.length" /> + </div> + <ul class="stage-event-list"> + <li v-for="mergeRequest in items" class="stage-event-item"> + <div class="item-details"> + <!-- FIXME: Pass an alt attribute here for accessibility --> + <user-avatar-image :img-src="mergeRequest.author.avatarUrl"/> + <h5 class="item-title merge-merquest-title"> + <a :href="mergeRequest.url"> + {{ mergeRequest.title }} + </a> + </h5> + <a :href="mergeRequest.url" class="issue-link">!{{ mergeRequest.iid }}</a> + · + <span> + {{ s__('OpenedNDaysAgo|Opened') }} + <a :href="mergeRequest.url" class="issue-date">{{ mergeRequest.createdAt }}</a> + </span> + <span> + {{ s__('ByAuthor|by') }} + <a :href="mergeRequest.author.webUrl" class="issue-author-link">{{ mergeRequest.author.name }}</a> + </span> + </div> + <div class="item-time"> + <total-time :time="mergeRequest.totalTime"></total-time> + </div> + </li> + </ul> + </div> +</template> diff --git a/app/assets/javascripts/cycle_analytics/components/stage_component.vue b/app/assets/javascripts/cycle_analytics/components/stage_component.vue new file mode 100644 index 00000000000..8c98bd249a1 --- /dev/null +++ b/app/assets/javascripts/cycle_analytics/components/stage_component.vue @@ -0,0 +1,57 @@ +<script> + import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue'; + import limitWarning from './limit_warning_component.vue'; + import totalTime from './total_time_component.vue'; + + export default { + props: { + items: Array, + stage: Object, + }, + components: { + userAvatarImage, + limitWarning, + totalTime, + }, + }; +</script> +<template> + <div> + <div class="events-description"> + {{ stage.description }} + <limit-warning :count="items.length" /> + </div> + <ul class="stage-event-list"> + <li + v-for="(issue, i) in items" + :key="i" + class="stage-event-item"> + <div class="item-details"> + <!-- FIXME: Pass an alt attribute here for accessibility --> + <user-avatar-image :img-src="issue.author.avatarUrl"/> + <h5 class="item-title issue-title"> + <a class="issue-title" :href="issue.url"> + {{ issue.title }} + </a> + </h5> + <a :href="issue.url" class="issue-link">#{{ issue.iid }}</a> + · + <span> + {{ s__('OpenedNDaysAgo|Opened') }} + <a :href="issue.url" class="issue-date">{{ issue.createdAt }}</a> + </span> + <span> + {{ s__('ByAuthor|by') }} + <a :href="issue.author.webUrl" class="issue-author-link"> + {{ issue.author.name }} + </a> + </span> + </div> + <div class="item-time"> + <total-time :time="issue.totalTime"/> + </div> + </li> + </ul> + </div> +</template> + diff --git a/app/assets/javascripts/cycle_analytics/components/stage_issue_component.js b/app/assets/javascripts/cycle_analytics/components/stage_issue_component.js deleted file mode 100644 index 5f4a0ac8590..00000000000 --- a/app/assets/javascripts/cycle_analytics/components/stage_issue_component.js +++ /dev/null @@ -1,52 +0,0 @@ -/* eslint-disable no-param-reassign */ -import Vue from 'vue'; -import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue'; - -const global = window.gl || (window.gl = {}); -global.cycleAnalytics = global.cycleAnalytics || {}; - -global.cycleAnalytics.StageIssueComponent = Vue.extend({ - props: { - items: Array, - stage: Object, - }, - components: { - userAvatarImage, - }, - template: ` - <div> - <div class="events-description"> - {{ stage.description }} - <limit-warning :count="items.length" /> - </div> - <ul class="stage-event-list"> - <li v-for="issue in items" class="stage-event-item"> - <div class="item-details"> - <!-- FIXME: Pass an alt attribute here for accessibility --> - <user-avatar-image :img-src="issue.author.avatarUrl"/> - <h5 class="item-title issue-title"> - <a class="issue-title" :href="issue.url"> - {{ issue.title }} - </a> - </h5> - <a :href="issue.url" class="issue-link">#{{ issue.iid }}</a> - · - <span> - {{ s__('OpenedNDaysAgo|Opened') }} - <a :href="issue.url" class="issue-date">{{ issue.createdAt }}</a> - </span> - <span> - {{ s__('ByAuthor|by') }} - <a :href="issue.author.webUrl" class="issue-author-link"> - {{ issue.author.name }} - </a> - </span> - </div> - <div class="item-time"> - <total-time :time="issue.totalTime"></total-time> - </div> - </li> - </ul> - </div> - `, -}); diff --git a/app/assets/javascripts/cycle_analytics/components/stage_plan_component.js b/app/assets/javascripts/cycle_analytics/components/stage_plan_component.js deleted file mode 100644 index 11fee5410d9..00000000000 --- a/app/assets/javascripts/cycle_analytics/components/stage_plan_component.js +++ /dev/null @@ -1,53 +0,0 @@ -/* eslint-disable no-param-reassign */ -import Vue from 'vue'; -import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue'; -import iconCommit from '../svg/icon_commit.svg'; - -const global = window.gl || (window.gl = {}); -global.cycleAnalytics = global.cycleAnalytics || {}; - -global.cycleAnalytics.StagePlanComponent = Vue.extend({ - props: { - items: Array, - stage: Object, - }, - components: { - userAvatarImage, - }, - data() { - return { iconCommit }; - }, - template: ` - <div> - <div class="events-description"> - {{ stage.description }} - <limit-warning :count="items.length" /> - </div> - <ul class="stage-event-list"> - <li v-for="commit in items" class="stage-event-item"> - <div class="item-details item-conmmit-component"> - <!-- FIXME: Pass an alt attribute here for accessibility --> - <user-avatar-image :img-src="commit.author.avatarUrl"/> - <h5 class="item-title commit-title"> - <a :href="commit.commitUrl"> - {{ commit.title }} - </a> - </h5> - <span> - {{ s__('FirstPushedBy|First') }} - <span class="commit-icon">${iconCommit}</span> - <a :href="commit.commitUrl" class="commit-hash-link commit-sha">{{ commit.shortSha }}</a> - {{ s__('FirstPushedBy|pushed by') }} - <a :href="commit.author.webUrl" class="commit-author-link"> - {{ commit.author.name }} - </a> - </span> - </div> - <div class="item-time"> - <total-time :time="commit.totalTime"></total-time> - </div> - </li> - </ul> - </div> - `, -}); diff --git a/app/assets/javascripts/cycle_analytics/components/stage_plan_component.vue b/app/assets/javascripts/cycle_analytics/components/stage_plan_component.vue new file mode 100644 index 00000000000..75d2f1fd70c --- /dev/null +++ b/app/assets/javascripts/cycle_analytics/components/stage_plan_component.vue @@ -0,0 +1,60 @@ +<script> + import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue'; + import iconCommit from '../svg/icon_commit.svg'; + import limitWarning from './limit_warning_component.vue'; + import totalTime from './total_time_component.vue'; + + export default { + props: { + items: Array, + stage: Object, + }, + components: { + userAvatarImage, + totalTime, + limitWarning, + }, + computed: { + iconCommit() { + return iconCommit; + }, + }, + }; +</script> +<template> + <div> + <div class="events-description"> + {{ stage.description }} + <limit-warning :count="items.length" /> + </div> + <ul class="stage-event-list"> + <li + v-for="(commit, i) in items" + :key="i" + class="stage-event-item"> + <div class="item-details item-conmmit-component"> + <!-- FIXME: Pass an alt attribute here for accessibility --> + <user-avatar-image :img-src="commit.author.avatarUrl"/> + <h5 class="item-title commit-title"> + <a :href="commit.commitUrl"> + {{ commit.title }} + </a> + </h5> + <span> + {{ s__('FirstPushedBy|First') }} + <span class="commit-icon" v-html="iconCommit"></span> + <a :href="commit.commitUrl" class="commit-hash-link commit-sha">{{ commit.shortSha }}</a> + {{ s__('FirstPushedBy|pushed by') }} + <a :href="commit.author.webUrl" class="commit-author-link"> + {{ commit.author.name }} + </a> + </span> + </div> + <div class="item-time"> + <total-time :time="commit.totalTime" /> + </div> + </li> + </ul> + </div> +</template> + diff --git a/app/assets/javascripts/cycle_analytics/components/stage_production_component.js b/app/assets/javascripts/cycle_analytics/components/stage_production_component.js deleted file mode 100644 index b7ba9360f70..00000000000 --- a/app/assets/javascripts/cycle_analytics/components/stage_production_component.js +++ /dev/null @@ -1,52 +0,0 @@ -/* eslint-disable no-param-reassign */ -import Vue from 'vue'; -import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue'; - -const global = window.gl || (window.gl = {}); -global.cycleAnalytics = global.cycleAnalytics || {}; - -global.cycleAnalytics.StageProductionComponent = Vue.extend({ - props: { - items: Array, - stage: Object, - }, - components: { - userAvatarImage, - }, - template: ` - <div> - <div class="events-description"> - {{ stage.description }} - <limit-warning :count="items.length" /> - </div> - <ul class="stage-event-list"> - <li v-for="issue in items" class="stage-event-item"> - <div class="item-details"> - <!-- FIXME: Pass an alt attribute here for accessibility --> - <user-avatar-image :img-src="issue.author.avatarUrl"/> - <h5 class="item-title issue-title"> - <a class="issue-title" :href="issue.url"> - {{ issue.title }} - </a> - </h5> - <a :href="issue.url" class="issue-link">#{{ issue.iid }}</a> - · - <span> - {{ s__('OpenedNDaysAgo|Opened') }} - <a :href="issue.url" class="issue-date">{{ issue.createdAt }}</a> - </span> - <span> - {{ s__('ByAuthor|by') }} - <a :href="issue.author.webUrl" class="issue-author-link"> - {{ issue.author.name }} - </a> - </span> - </div> - <div class="item-time"> - <total-time :time="issue.totalTime"></total-time> - </div> - </li> - </ul> - </div> - `, -}); diff --git a/app/assets/javascripts/cycle_analytics/components/stage_review_component.js b/app/assets/javascripts/cycle_analytics/components/stage_review_component.js deleted file mode 100644 index f41a0d0e4ff..00000000000 --- a/app/assets/javascripts/cycle_analytics/components/stage_review_component.js +++ /dev/null @@ -1,62 +0,0 @@ -/* eslint-disable no-param-reassign */ -import Vue from 'vue'; -import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue'; - -const global = window.gl || (window.gl = {}); -global.cycleAnalytics = global.cycleAnalytics || {}; - -global.cycleAnalytics.StageReviewComponent = Vue.extend({ - props: { - items: Array, - stage: Object, - }, - components: { - userAvatarImage, - }, - template: ` - <div> - <div class="events-description"> - {{ stage.description }} - <limit-warning :count="items.length" /> - </div> - <ul class="stage-event-list"> - <li v-for="mergeRequest in items" class="stage-event-item"> - <div class="item-details"> - <!-- FIXME: Pass an alt attribute here for accessibility --> - <user-avatar-image :img-src="mergeRequest.author.avatarUrl"/> - <h5 class="item-title merge-merquest-title"> - <a :href="mergeRequest.url"> - {{ mergeRequest.title }} - </a> - </h5> - <a :href="mergeRequest.url" class="issue-link">!{{ mergeRequest.iid }}</a> - · - <span> - {{ s__('OpenedNDaysAgo|Opened') }} - <a :href="mergeRequest.url" class="issue-date">{{ mergeRequest.createdAt }}</a> - </span> - <span> - {{ s__('ByAuthor|by') }} - <a :href="mergeRequest.author.webUrl" class="issue-author-link">{{ mergeRequest.author.name }}</a> - </span> - <template v-if="mergeRequest.state === 'closed'"> - <span class="merge-request-state"> - <i class="fa fa-ban"></i> - {{ mergeRequest.state.toUpperCase() }} - </span> - </template> - <template v-else> - <span class="merge-request-branch" v-if="mergeRequest.branch"> - <i class= "fa fa-code-fork"></i> - <a :href="mergeRequest.branch.url">{{ mergeRequest.branch.name }}</a> - </span> - </template> - </div> - <div class="item-time"> - <total-time :time="mergeRequest.totalTime"></total-time> - </div> - </li> - </ul> - </div> - `, -}); diff --git a/app/assets/javascripts/cycle_analytics/components/stage_review_component.vue b/app/assets/javascripts/cycle_analytics/components/stage_review_component.vue new file mode 100644 index 00000000000..f54ea7df522 --- /dev/null +++ b/app/assets/javascripts/cycle_analytics/components/stage_review_component.vue @@ -0,0 +1,66 @@ +<script> + import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue'; + import limitWarning from './limit_warning_component.vue'; + import totalTime from './total_time_component.vue'; + + export default { + props: { + items: Array, + stage: Object, + }, + components: { + userAvatarImage, + totalTime, + limitWarning, + }, + }; +</script> +<template> + <div> + <div class="events-description"> + {{ stage.description }} + <limit-warning :count="items.length" /> + </div> + <ul class="stage-event-list"> + <li + v-for="(mergeRequest, i) in items" + :key="i" + class="stage-event-item"> + <div class="item-details"> + <!-- FIXME: Pass an alt attribute here for accessibility --> + <user-avatar-image :img-src="mergeRequest.author.avatarUrl"/> + <h5 class="item-title merge-merquest-title"> + <a :href="mergeRequest.url"> + {{ mergeRequest.title }} + </a> + </h5> + <a :href="mergeRequest.url" class="issue-link">!{{ mergeRequest.iid }}</a> + · + <span> + {{ s__('OpenedNDaysAgo|Opened') }} + <a :href="mergeRequest.url" class="issue-date">{{ mergeRequest.createdAt }}</a> + </span> + <span> + {{ s__('ByAuthor|by') }} + <a :href="mergeRequest.author.webUrl" class="issue-author-link">{{ mergeRequest.author.name }}</a> + </span> + <template v-if="mergeRequest.state === 'closed'"> + <span class="merge-request-state"> + <i class="fa fa-ban"></i> + {{ mergeRequest.state.toUpperCase() }} + </span> + </template> + <template v-else> + <span class="merge-request-branch" v-if="mergeRequest.branch"> + <i class= "fa fa-code-fork"></i> + <a :href="mergeRequest.branch.url">{{ mergeRequest.branch.name }}</a> + </span> + </template> + </div> + <div class="item-time"> + <total-time :time="mergeRequest.totalTime"/> + </div> + </li> + </ul> + </div> +</template> diff --git a/app/assets/javascripts/cycle_analytics/components/stage_staging_component.js b/app/assets/javascripts/cycle_analytics/components/stage_staging_component.js deleted file mode 100644 index d7c906c9d39..00000000000 --- a/app/assets/javascripts/cycle_analytics/components/stage_staging_component.js +++ /dev/null @@ -1,53 +0,0 @@ -/* eslint-disable no-param-reassign */ -import Vue from 'vue'; -import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue'; -import iconBranch from '../svg/icon_branch.svg'; - -const global = window.gl || (window.gl = {}); -global.cycleAnalytics = global.cycleAnalytics || {}; - -global.cycleAnalytics.StageStagingComponent = Vue.extend({ - props: { - items: Array, - stage: Object, - }, - data() { - return { iconBranch }; - }, - components: { - userAvatarImage, - }, - template: ` - <div> - <div class="events-description"> - {{ stage.description }} - <limit-warning :count="items.length" /> - </div> - <ul class="stage-event-list"> - <li v-for="build in items" class="stage-event-item item-build-component"> - <div class="item-details"> - <!-- FIXME: Pass an alt attribute here for accessibility --> - <user-avatar-image :img-src="build.author.avatarUrl"/> - <h5 class="item-title"> - <a :href="build.url" class="pipeline-id">#{{ build.id }}</a> - <i class="fa fa-code-fork"></i> - <a :href="build.branch.url" class="ref-name">{{ build.branch.name }}</a> - <span class="icon-branch">${iconBranch}</span> - <a :href="build.commitUrl" class="commit-sha">{{ build.shortSha }}</a> - </h5> - <span> - <a :href="build.url" class="build-date">{{ build.date }}</a> - {{ s__('ByAuthor|by') }} - <a :href="build.author.webUrl" class="issue-author-link"> - {{ build.author.name }} - </a> - </span> - </div> - <div class="item-time"> - <total-time :time="build.totalTime"></total-time> - </div> - </li> - </ul> - </div> - `, -}); diff --git a/app/assets/javascripts/cycle_analytics/components/stage_staging_component.vue b/app/assets/javascripts/cycle_analytics/components/stage_staging_component.vue new file mode 100644 index 00000000000..5d95ddcd90e --- /dev/null +++ b/app/assets/javascripts/cycle_analytics/components/stage_staging_component.vue @@ -0,0 +1,59 @@ +<script> + import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue'; + import iconBranch from '../svg/icon_branch.svg'; + import limitWarning from './limit_warning_component.vue'; + import totalTime from './total_time_component.vue'; + + export default { + props: { + items: Array, + stage: Object, + }, + components: { + userAvatarImage, + totalTime, + limitWarning, + }, + computed: { + iconBranch() { + return iconBranch; + }, + }, + }; +</script> +<template> + <div> + <div class="events-description"> + {{ stage.description }} + <limit-warning :count="items.length" /> + </div> + <ul class="stage-event-list"> + <li + v-for="(build, i) in items" + class="stage-event-item item-build-component" + :key="i"> + <div class="item-details"> + <!-- FIXME: Pass an alt attribute here for accessibility --> + <user-avatar-image :img-src="build.author.avatarUrl"/> + <h5 class="item-title"> + <a :href="build.url" class="pipeline-id">#{{ build.id }}</a> + <i class="fa fa-code-fork"></i> + <a :href="build.branch.url" class="ref-name">{{ build.branch.name }}</a> + <span class="icon-branch" v-html="iconBranch"></span> + <a :href="build.commitUrl" class="commit-sha">{{ build.shortSha }}</a> + </h5> + <span> + <a :href="build.url" class="build-date">{{ build.date }}</a> + {{ s__('ByAuthor|by') }} + <a :href="build.author.webUrl" class="issue-author-link"> + {{ build.author.name }} + </a> + </span> + </div> + <div class="item-time"> + <total-time :time="build.totalTime"/> + </div> + </li> + </ul> + </div> +</template> diff --git a/app/assets/javascripts/cycle_analytics/components/stage_test_component.js b/app/assets/javascripts/cycle_analytics/components/stage_test_component.js deleted file mode 100644 index 78cc97eea0b..00000000000 --- a/app/assets/javascripts/cycle_analytics/components/stage_test_component.js +++ /dev/null @@ -1,49 +0,0 @@ -/* eslint-disable no-param-reassign */ -import Vue from 'vue'; -import iconBuildStatus from '../svg/icon_build_status.svg'; -import iconBranch from '../svg/icon_branch.svg'; - -const global = window.gl || (window.gl = {}); -global.cycleAnalytics = global.cycleAnalytics || {}; - -global.cycleAnalytics.StageTestComponent = Vue.extend({ - props: { - items: Array, - stage: Object, - }, - data() { - return { iconBuildStatus, iconBranch }; - }, - template: ` - <div> - <div class="events-description"> - {{ stage.description }} - <limit-warning :count="items.length" /> - </div> - <ul class="stage-event-list"> - <li v-for="build in items" class="stage-event-item item-build-component"> - <div class="item-details"> - <h5 class="item-title"> - <span class="icon-build-status">${iconBuildStatus}</span> - <a :href="build.url" class="item-build-name">{{ build.name }}</a> - · - <a :href="build.url" class="pipeline-id">#{{ build.id }}</a> - <i class="fa fa-code-fork"></i> - <a :href="build.branch.url" class="ref-name">{{ build.branch.name }}</a> - <span class="icon-branch">${iconBranch}</span> - <a :href="build.commitUrl" class="commit-sha">{{ build.shortSha }}</a> - </h5> - <span> - <a :href="build.url" class="issue-date"> - {{ build.date }} - </a> - </span> - </div> - <div class="item-time"> - <total-time :time="build.totalTime"></total-time> - </div> - </li> - </ul> - </div> - `, -}); diff --git a/app/assets/javascripts/cycle_analytics/components/stage_test_component.vue b/app/assets/javascripts/cycle_analytics/components/stage_test_component.vue new file mode 100644 index 00000000000..04d5440b77b --- /dev/null +++ b/app/assets/javascripts/cycle_analytics/components/stage_test_component.vue @@ -0,0 +1,60 @@ +<script> + import iconBuildStatus from '../svg/icon_build_status.svg'; + import iconBranch from '../svg/icon_branch.svg'; + import limitWarning from './limit_warning_component.vue'; + import totalTime from './total_time_component.vue'; + + export default { + props: { + items: Array, + stage: Object, + }, + components: { + totalTime, + limitWarning, + }, + computed: { + iconBuildStatus() { + return iconBuildStatus; + }, + iconBranch() { + return iconBranch; + }, + }, + }; +</script> +<template> + <div> + <div class="events-description"> + {{ stage.description }} + <limit-warning :count="items.length" /> + </div> + <ul class="stage-event-list"> + <li + v-for="(build, i) in items" + :key="i" + class="stage-event-item item-build-component"> + <div class="item-details"> + <h5 class="item-title"> + <span class="icon-build-status" v-html="iconBuildStatus"></span> + <a :href="build.url" class="item-build-name">{{ build.name }}</a> + · + <a :href="build.url" class="pipeline-id">#{{ build.id }}</a> + <i class="fa fa-code-fork"></i> + <a :href="build.branch.url" class="ref-name">{{ build.branch.name }}</a> + <span class="icon-branch" v-html="iconBranch"></span> + <a :href="build.commitUrl" class="commit-sha">{{ build.shortSha }}</a> + </h5> + <span> + <a :href="build.url" class="issue-date"> + {{ build.date }} + </a> + </span> + </div> + <div class="item-time"> + <total-time :time="build.totalTime"/> + </div> + </li> + </ul> + </div> +</template> diff --git a/app/assets/javascripts/cycle_analytics/components/total_time_component.js b/app/assets/javascripts/cycle_analytics/components/total_time_component.js deleted file mode 100644 index d5e6167b2a8..00000000000 --- a/app/assets/javascripts/cycle_analytics/components/total_time_component.js +++ /dev/null @@ -1,25 +0,0 @@ -/* eslint-disable no-param-reassign */ - -import Vue from 'vue'; - -const global = window.gl || (window.gl = {}); -global.cycleAnalytics = global.cycleAnalytics || {}; - -global.cycleAnalytics.TotalTimeComponent = Vue.extend({ - props: { - time: Object, - }, - template: ` - <span class="total-time"> - <template v-if="Object.keys(time).length"> - <template v-if="time.days">{{ time.days }} <span>{{ n__('day', 'days', time.days) }}</span></template> - <template v-if="time.hours">{{ time.hours }} <span>{{ n__('Time|hr', 'Time|hrs', time.hours) }}</span></template> - <template v-if="time.mins && !time.days">{{ time.mins }} <span>{{ n__('Time|min', 'Time|mins', time.mins) }}</span></template> - <template v-if="time.seconds && Object.keys(time).length === 1 || time.seconds === 0">{{ time.seconds }} <span>{{ s__('Time|s') }}</span></template> - </template> - <template v-else> - -- - </template> - </span> - `, -}); diff --git a/app/assets/javascripts/cycle_analytics/components/total_time_component.vue b/app/assets/javascripts/cycle_analytics/components/total_time_component.vue new file mode 100644 index 00000000000..9941b997b3f --- /dev/null +++ b/app/assets/javascripts/cycle_analytics/components/total_time_component.vue @@ -0,0 +1,29 @@ +<script> + export default { + props: { + time: { + type: Object, + required: false, + default: () => ({}), + }, + }, + computed: { + hasData() { + return Object.keys(this.time).length; + }, + }, + }; +</script> +<template> + <span class="total-time"> + <template v-if="hasData"> + <template v-if="time.days">{{ time.days }} <span>{{ n__('day', 'days', time.days) }}</span></template> + <template v-if="time.hours">{{ time.hours }} <span>{{ n__('Time|hr', 'Time|hrs', time.hours) }}</span></template> + <template v-if="time.mins && !time.days">{{ time.mins }} <span>{{ n__('Time|min', 'Time|mins', time.mins) }}</span></template> + <template v-if="time.seconds && hasDa === 1 || time.seconds === 0">{{ time.seconds }} <span>{{ s__('Time|s') }}</span></template> + </template> + <template v-else> + -- + </template> + </span> +</template> diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js index 6583e471a48..991fcf114da 100644 --- a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js +++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js @@ -3,60 +3,61 @@ import Vue from 'vue'; import Cookies from 'js-cookie'; import Translate from '../vue_shared/translate'; -import LimitWarningComponent from './components/limit_warning_component'; -import './components/stage_code_component'; -import './components/stage_issue_component'; -import './components/stage_plan_component'; -import './components/stage_production_component'; -import './components/stage_review_component'; -import './components/stage_staging_component'; -import './components/stage_test_component'; -import './components/total_time_component'; -import './cycle_analytics_service'; -import './cycle_analytics_store'; +import stageCodeComponent from './components/stage_code_component.vue'; +import stagePlanComponent from './components/stage_plan_component.vue'; +import stageComponent from './components/stage_component.vue'; +import stageReviewComponent from './components/stage_review_component.vue'; +import stageStagingComponent from './components/stage_staging_component.vue'; +import stageTestComponent from './components/stage_test_component.vue'; +import CycleAnalyticsService from './cycle_analytics_service'; +import CycleAnalyticsStore from './cycle_analytics_store'; Vue.use(Translate); $(() => { const OVERVIEW_DIALOG_COOKIE = 'cycle_analytics_help_dismissed'; - const cycleAnalyticsEl = document.querySelector('#cycle-analytics'); - const cycleAnalyticsStore = gl.cycleAnalytics.CycleAnalyticsStore; - const cycleAnalyticsService = new gl.cycleAnalytics.CycleAnalyticsService({ - requestPath: cycleAnalyticsEl.dataset.requestPath, - }); gl.cycleAnalyticsApp = new Vue({ el: '#cycle-analytics', name: 'CycleAnalytics', - data: { - state: cycleAnalyticsStore.state, - isLoading: false, - isLoadingStage: false, - isEmptyStage: false, - hasError: false, - startDate: 30, - isOverviewDialogDismissed: Cookies.get(OVERVIEW_DIALOG_COOKIE), + data() { + const cycleAnalyticsEl = document.querySelector('#cycle-analytics'); + const cycleAnalyticsService = new CycleAnalyticsService({ + requestPath: cycleAnalyticsEl.dataset.requestPath, + }); + + return { + store: CycleAnalyticsStore, + state: CycleAnalyticsStore.state, + isLoading: false, + isLoadingStage: false, + isEmptyStage: false, + hasError: false, + startDate: 30, + isOverviewDialogDismissed: Cookies.get(OVERVIEW_DIALOG_COOKIE), + service: cycleAnalyticsService, + }; }, computed: { currentStage() { - return cycleAnalyticsStore.currentActiveStage(); + return this.store.currentActiveStage(); }, }, components: { - 'stage-issue-component': gl.cycleAnalytics.StageIssueComponent, - 'stage-plan-component': gl.cycleAnalytics.StagePlanComponent, - 'stage-code-component': gl.cycleAnalytics.StageCodeComponent, - 'stage-test-component': gl.cycleAnalytics.StageTestComponent, - 'stage-review-component': gl.cycleAnalytics.StageReviewComponent, - 'stage-staging-component': gl.cycleAnalytics.StageStagingComponent, - 'stage-production-component': gl.cycleAnalytics.StageProductionComponent, + 'stage-issue-component': stageComponent, + 'stage-plan-component': stagePlanComponent, + 'stage-code-component': stageCodeComponent, + 'stage-test-component': stageTestComponent, + 'stage-review-component': stageReviewComponent, + 'stage-staging-component': stageStagingComponent, + 'stage-production-component': stageComponent, }, created() { this.fetchCycleAnalyticsData(); }, methods: { handleError() { - cycleAnalyticsStore.setErrorState(true); + this.store.setErrorState(true); return new Flash('There was an error while fetching cycle analytics data.'); }, initDropdown() { @@ -77,17 +78,17 @@ $(() => { this.isLoading = true; - cycleAnalyticsService + this.service .fetchCycleAnalyticsData(fetchOptions) - .done((response) => { - cycleAnalyticsStore.setCycleAnalyticsData(response); + .then(resp => resp.json()) + .then((response) => { + this.store.setCycleAnalyticsData(response); this.selectDefaultStage(); this.initDropdown(); + this.isLoading = false; }) - .error(() => { + .catch(() => { this.handleError(); - }) - .always(() => { this.isLoading = false; }); }, @@ -100,27 +101,27 @@ $(() => { if (this.currentStage === stage) return; if (!stage.isUserAllowed) { - cycleAnalyticsStore.setActiveStage(stage); + this.store.setActiveStage(stage); return; } this.isLoadingStage = true; - cycleAnalyticsStore.setStageEvents([], stage); - cycleAnalyticsStore.setActiveStage(stage); + this.store.setStageEvents([], stage); + this.store.setActiveStage(stage); - cycleAnalyticsService + this.service .fetchStageData({ stage, startDate: this.startDate, }) - .done((response) => { + .then(resp => resp.json()) + .then((response) => { this.isEmptyStage = !response.events.length; - cycleAnalyticsStore.setStageEvents(response.events, stage); + this.store.setStageEvents(response.events, stage); + this.isLoadingStage = false; }) - .error(() => { + .catch(() => { this.isEmptyStage = true; - }) - .always(() => { this.isLoadingStage = false; }); }, @@ -130,8 +131,4 @@ $(() => { }, }, }); - - // Register global components - Vue.component('limit-warning', LimitWarningComponent); - Vue.component('total-time', gl.cycleAnalytics.TotalTimeComponent); }); diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_service.js b/app/assets/javascripts/cycle_analytics/cycle_analytics_service.js index 6504d7db2f2..f496c38208d 100644 --- a/app/assets/javascripts/cycle_analytics/cycle_analytics_service.js +++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_service.js @@ -1,27 +1,16 @@ -/* eslint-disable no-param-reassign */ +import Vue from 'vue'; +import VueResource from 'vue-resource'; -const global = window.gl || (window.gl = {}); -global.cycleAnalytics = global.cycleAnalytics || {}; +Vue.use(VueResource); -class CycleAnalyticsService { +export default class CycleAnalyticsService { constructor(options) { this.requestPath = options.requestPath; + this.cycleAnalytics = Vue.resource(this.requestPath); } - fetchCycleAnalyticsData(options) { - options = options || { startDate: 30 }; - - return $.ajax({ - url: this.requestPath, - method: 'GET', - dataType: 'json', - contentType: 'application/json', - data: { - cycle_analytics: { - start_date: options.startDate, - }, - }, - }); + fetchCycleAnalyticsData(options = { startDate: 30 }) { + return this.cycleAnalytics.get({ cycle_analytics: { start_date: options.startDate } }); } fetchStageData(options) { @@ -30,12 +19,12 @@ class CycleAnalyticsService { startDate, } = options; - return $.get(`${this.requestPath}/events/${stage.name}.json`, { - cycle_analytics: { - start_date: startDate, + return Vue.http.get(`${this.requestPath}/events/${stage.name}.json`, { + params: { + cycle_analytics: { + start_date: startDate, + }, }, }); } } - -global.cycleAnalytics.CycleAnalyticsService = CycleAnalyticsService; diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js b/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js index 991f8c1f6fd..8bf9ae17de0 100644 --- a/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js +++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js @@ -4,9 +4,6 @@ import { __ } from '../locale'; import '../lib/utils/text_utility'; import DEFAULT_EVENT_OBJECTS from './default_event_objects'; -const global = window.gl || (window.gl = {}); -global.cycleAnalytics = global.cycleAnalytics || {}; - const EMPTY_STAGE_TEXTS = { issue: __('The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.'), plan: __('The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.'), @@ -17,7 +14,7 @@ const EMPTY_STAGE_TEXTS = { production: __('The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.'), }; -global.cycleAnalytics.CycleAnalyticsStore = { +export default { state: { summary: '', stats: '', diff --git a/app/assets/javascripts/diff.js b/app/assets/javascripts/diff.js index 6a008112203..ae8338f5fd2 100644 --- a/app/assets/javascripts/diff.js +++ b/app/assets/javascripts/diff.js @@ -24,7 +24,8 @@ class Diff { if (!isBound) { $(document) .on('click', '.js-unfold', this.handleClickUnfold.bind(this)) - .on('click', '.diff-line-num a', this.handleClickLineNum.bind(this)); + .on('click', '.diff-line-num a', this.handleClickLineNum.bind(this)) + .on('mousedown', 'td.line_content.parallel', this.handleParallelLineDown.bind(this)); isBound = true; } @@ -100,6 +101,18 @@ class Diff { this.highlightSelectedLine(); } + handleParallelLineDown(e) { + const line = $(e.currentTarget); + const table = line.closest('table'); + + table.removeClass('left-side-selected right-side-selected'); + + const lineClass = ['left-side', 'right-side'].filter(name => line.hasClass(name))[0]; + if (lineClass) { + table.addClass(`${lineClass}-selected`); + } + } + diffViewType() { return $('.inline-parallel-buttons a.active').data('view-type'); } diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index 31214818496..bbaa4e4d91e 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -14,7 +14,6 @@ /* global NotificationsDropdown */ /* global GroupAvatar */ /* global LineHighlighter */ -/* global ProjectFork */ /* global BuildArtifacts */ /* global GroupsSelect */ /* global Search */ @@ -476,7 +475,9 @@ import { ajaxGet, convertPermissionToBoolean } from './lib/utils/common_utils'; shortcut_handler = true; break; case 'projects:forks:new': - new ProjectFork(); + import(/* webpackChunkName: 'project_fork' */ './project_fork') + .then(fork => fork.default()) + .catch(() => {}); break; case 'projects:artifacts:browse': new ShortcutsNavigation(); diff --git a/app/assets/javascripts/environments/components/environment.vue b/app/assets/javascripts/environments/components/environment.vue index 14fde1afb16..ce5f6219a3e 100644 --- a/app/assets/javascripts/environments/components/environment.vue +++ b/app/assets/javascripts/environments/components/environment.vue @@ -163,7 +163,7 @@ export default { this.service.postAction(endpoint) .then(() => this.fetchEnvironments()) - .catch(() => new Flash('An error occured while making the request.')); + .catch(() => new Flash('An error occurred while making the request.')); } }, diff --git a/app/assets/javascripts/environments/folder/environments_folder_view.vue b/app/assets/javascripts/environments/folder/environments_folder_view.vue index 35891240239..01e70c0bbb7 100644 --- a/app/assets/javascripts/environments/folder/environments_folder_view.vue +++ b/app/assets/javascripts/environments/folder/environments_folder_view.vue @@ -158,7 +158,7 @@ export default { this.service.postAction(endpoint) .then(() => this.fetchEnvironments()) - .catch(() => new Flash('An error occured while making the request.')); + .catch(() => new Flash('An error occurred while making the request.')); } }, }, diff --git a/app/assets/javascripts/files_comment_button.js b/app/assets/javascripts/files_comment_button.js index d02e4cd5876..a00d29a845a 100644 --- a/app/assets/javascripts/files_comment_button.js +++ b/app/assets/javascripts/files_comment_button.js @@ -7,6 +7,8 @@ * causes reflows, visit https://gist.github.com/paulirish/5d52fb081b3570c81e3a */ +import Cookies from 'js-cookie'; + const LINE_NUMBER_CLASS = 'diff-line-num'; const UNFOLDABLE_LINE_CLASS = 'js-unfold'; const NO_COMMENT_CLASS = 'no-comment-btn'; @@ -27,9 +29,7 @@ export default { this.userCanCreateNote = $diffFile.closest(DIFF_CONTAINER_SELECTOR).data('can-create-note') === ''; } - if (typeof notes !== 'undefined' && !this.isParallelView) { - this.isParallelView = notes.isParallelView && notes.isParallelView(); - } + this.isParallelView = Cookies.get('diff_view') === 'parallel'; if (this.userCanCreateNote) { $diffFile.on('mouseover', LINE_COLUMN_CLASSES, e => this.showButton(this.isParallelView, e)) diff --git a/app/assets/javascripts/filtered_search/dropdown_emoji.js b/app/assets/javascripts/filtered_search/dropdown_emoji.js index f9bbbf0cbc1..ada14d2053c 100644 --- a/app/assets/javascripts/filtered_search/dropdown_emoji.js +++ b/app/assets/javascripts/filtered_search/dropdown_emoji.js @@ -14,7 +14,7 @@ class DropdownEmoji extends gl.FilteredSearchDropdown { loadingTemplate: this.loadingTemplate, onError() { /* eslint-disable no-new */ - new Flash('An error occured fetching the dropdown data.'); + new Flash('An error occurred fetching the dropdown data.'); /* eslint-enable no-new */ }, }, diff --git a/app/assets/javascripts/filtered_search/dropdown_non_user.js b/app/assets/javascripts/filtered_search/dropdown_non_user.js index 0bc4b6f22a9..b32d589481d 100644 --- a/app/assets/javascripts/filtered_search/dropdown_non_user.js +++ b/app/assets/javascripts/filtered_search/dropdown_non_user.js @@ -17,7 +17,7 @@ class DropdownNonUser extends gl.FilteredSearchDropdown { preprocessing, onError() { /* eslint-disable no-new */ - new Flash('An error occured fetching the dropdown data.'); + new Flash('An error occurred fetching the dropdown data.'); /* eslint-enable no-new */ }, }, diff --git a/app/assets/javascripts/filtered_search/dropdown_user.js b/app/assets/javascripts/filtered_search/dropdown_user.js index 720fbc87ea0..ce8817b1b2e 100644 --- a/app/assets/javascripts/filtered_search/dropdown_user.js +++ b/app/assets/javascripts/filtered_search/dropdown_user.js @@ -26,7 +26,7 @@ class DropdownUser extends gl.FilteredSearchDropdown { }, onError() { /* eslint-disable no-new */ - new Flash('An error occured fetching the dropdown data.'); + new Flash('An error occurred fetching the dropdown data.'); /* eslint-enable no-new */ }, }, diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js index 9178fec085a..a44dc279a6f 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_manager.js +++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js @@ -36,7 +36,7 @@ class FilteredSearchManager { .catch((error) => { if (error.name === 'RecentSearchesServiceError') return undefined; // eslint-disable-next-line no-new - new window.Flash('An error occured while parsing recent searches'); + new window.Flash('An error occurred while parsing recent searches'); // Gracefully fail to empty array return []; }) diff --git a/app/assets/javascripts/fly_out_nav.js b/app/assets/javascripts/fly_out_nav.js index 157280d66e3..98837c3b2a0 100644 --- a/app/assets/javascripts/fly_out_nav.js +++ b/app/assets/javascripts/fly_out_nav.js @@ -34,7 +34,7 @@ export const canShowActiveSubItems = (el) => { export const canShowSubItems = () => bp.getBreakpointSize() === 'sm' || bp.getBreakpointSize() === 'md' || bp.getBreakpointSize() === 'lg'; export const getHideSubItemsInterval = () => { - if (!currentOpenMenu) return 0; + if (!currentOpenMenu || !mousePos.length) return 0; const currentMousePos = mousePos[mousePos.length - 1]; const prevMousePos = mousePos[0]; diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index 50d822eba5a..ff218ccad62 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -548,6 +548,7 @@ GitLabDropdown = (function() { GitLabDropdown.prototype.positionMenuAbove = function() { var $menu = this.dropdown.find('.dropdown-menu'); + $menu.addClass('dropdown-open-top'); $menu.css('top', 'initial'); $menu.css('bottom', '100%'); }; diff --git a/app/assets/javascripts/issuable_context.js b/app/assets/javascripts/issuable_context.js index 70c364e51fe..1d305f1eb2f 100644 --- a/app/assets/javascripts/issuable_context.js +++ b/app/assets/javascripts/issuable_context.js @@ -67,10 +67,13 @@ const PARTICIPANTS_ROW_COUNT = 7; originalText = $(this).data("original-text"); if (currentText === originalText) { $(this).text(lessText); + + if (gl.lazyLoader) gl.lazyLoader.loadCheck(); } else { $(this).text(originalText); } - return $(".js-participants-hidden").toggle(); + + $(".js-participants-hidden").toggle(); }; return IssuableContext; diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js index ea2d61af9be..423a25fbdfa 100644 --- a/app/assets/javascripts/lib/utils/common_utils.js +++ b/app/assets/javascripts/lib/utils/common_utils.js @@ -71,6 +71,7 @@ export const handleLocationHash = () => { // This is required to handle non-unicode characters in hash hash = decodeURIComponent(hash); + const target = document.getElementById(hash) || document.getElementById(`user-content-${hash}`); const fixedTabs = document.querySelector('.js-tabs-affix'); const fixedDiffStats = document.querySelector('.js-diff-files-changed.is-stuck'); const fixedNav = document.querySelector('.navbar-gitlab'); @@ -78,25 +79,19 @@ export const handleLocationHash = () => { let adjustment = 0; if (fixedNav) adjustment -= fixedNav.offsetHeight; - // scroll to user-generated markdown anchor if we cannot find a match - if (document.getElementById(hash) === null) { - const target = document.getElementById(`user-content-${hash}`); - if (target && target.scrollIntoView) { - target.scrollIntoView(true); - window.scrollBy(0, adjustment); - } - } else { - // only adjust for fixedTabs when not targeting user-generated content - if (fixedTabs) { - adjustment -= fixedTabs.offsetHeight; - } + if (target && target.scrollIntoView) { + target.scrollIntoView(true); + } - if (fixedDiffStats) { - adjustment -= fixedDiffStats.offsetHeight; - } + if (fixedTabs) { + adjustment -= fixedTabs.offsetHeight; + } - window.scrollBy(0, adjustment); + if (fixedDiffStats) { + adjustment -= fixedDiffStats.offsetHeight; } + + window.scrollBy(0, adjustment); }; // Check if element scrolled into viewport from above or below diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js index 1d1763c3963..29fc91733b3 100644 --- a/app/assets/javascripts/lib/utils/datetime_utility.js +++ b/app/assets/javascripts/lib/utils/datetime_utility.js @@ -55,7 +55,7 @@ window.dateFormat = dateFormat; if (!timeagoInstance) { const localeRemaining = function(number, index) { return [ - [s__('Timeago|less than a minute ago'), s__('Timeago|a while')], + [s__('Timeago|less than a minute ago'), s__('Timeago|in a while')], [s__('Timeago|less than a minute ago'), s__('Timeago|%s seconds remaining')], [s__('Timeago|about a minute ago'), s__('Timeago|1 minute remaining')], [s__('Timeago|%s minutes ago'), s__('Timeago|%s minutes remaining')], @@ -73,7 +73,7 @@ window.dateFormat = dateFormat; }; locale = function(number, index) { return [ - [s__('Timeago|less than a minute ago'), s__('Timeago|a while')], + [s__('Timeago|less than a minute ago'), s__('Timeago|in a while')], [s__('Timeago|less than a minute ago'), s__('Timeago|in %s seconds')], [s__('Timeago|about a minute ago'), s__('Timeago|in 1 minute')], [s__('Timeago|%s minutes ago'), s__('Timeago|in %s minutes')], diff --git a/app/assets/javascripts/lib/utils/sticky.js b/app/assets/javascripts/lib/utils/sticky.js index 283c0ec0410..64db42701ce 100644 --- a/app/assets/javascripts/lib/utils/sticky.js +++ b/app/assets/javascripts/lib/utils/sticky.js @@ -1,14 +1,34 @@ -export const isSticky = (el, scrollY, stickyTop) => { +export const createPlaceholder = () => { + const placeholder = document.createElement('div'); + placeholder.classList.add('sticky-placeholder'); + + return placeholder; +}; + +export const isSticky = (el, scrollY, stickyTop, insertPlaceholder) => { const top = Math.floor(el.offsetTop - scrollY); - if (top <= stickyTop) { + if (top <= stickyTop && !el.classList.contains('is-stuck')) { + const placeholder = insertPlaceholder ? createPlaceholder() : null; + const heightBefore = el.offsetHeight; + el.classList.add('is-stuck'); - } else { + + if (insertPlaceholder) { + el.parentNode.insertBefore(placeholder, el.nextElementSibling); + + placeholder.style.height = `${heightBefore - el.offsetHeight}px`; + } + } else if (top > stickyTop && el.classList.contains('is-stuck')) { el.classList.remove('is-stuck'); + + if (insertPlaceholder && el.nextElementSibling && el.nextElementSibling.classList.contains('sticky-placeholder')) { + el.nextElementSibling.remove(); + } } }; -export default (el) => { +export default (el, insertPlaceholder = true) => { if (!el) return; const computedStyle = window.getComputedStyle(el); @@ -17,7 +37,7 @@ export default (el) => { const stickyTop = parseInt(computedStyle.top, 10); - document.addEventListener('scroll', () => isSticky(el, window.scrollY, stickyTop), { + document.addEventListener('scroll', () => isSticky(el, window.scrollY, stickyTop, insertPlaceholder), { passive: true, }); }; diff --git a/app/assets/javascripts/line_highlighter.js b/app/assets/javascripts/line_highlighter.js index 7400c22543f..a16d00b5cef 100644 --- a/app/assets/javascripts/line_highlighter.js +++ b/app/assets/javascripts/line_highlighter.js @@ -28,148 +28,149 @@ // </div> // </div> // -(function() { - this.LineHighlighter = (function() { - // CSS class applied to highlighted lines - LineHighlighter.prototype.highlightClass = 'hll'; - - // Internal copy of location.hash so we're not dependent on `location` in tests - LineHighlighter.prototype._hash = ''; - - function LineHighlighter(hash) { - if (hash == null) { - // Initialize a LineHighlighter object - // - // hash - String URL hash for dependency injection in tests - hash = location.hash; - } - this.setHash = this.setHash.bind(this); - this.highlightLine = this.highlightLine.bind(this); - this.clickHandler = this.clickHandler.bind(this); - this.highlightHash = this.highlightHash.bind(this); - this._hash = hash; - this.bindEvents(); - this.highlightHash(); - } - LineHighlighter.prototype.bindEvents = function() { - const $fileHolder = $('.file-holder'); - $fileHolder.on('click', 'a[data-line-number]', this.clickHandler); - $fileHolder.on('highlight:line', this.highlightHash); - }; - - LineHighlighter.prototype.highlightHash = function() { - var range; - if (this._hash !== '') { - range = this.hashToRange(this._hash); - if (range[0]) { - this.highlightRange(range); - $.scrollTo("#L" + range[0], { - // Scroll to the first highlighted line on initial load - // Offset -50 for the sticky top bar, and another -100 for some context - offset: -150 - }); - } - } - }; - - LineHighlighter.prototype.clickHandler = function(event) { - var current, lineNumber, range; - event.preventDefault(); - this.clearHighlight(); - lineNumber = $(event.target).closest('a').data('line-number'); - current = this.hashToRange(this._hash); - if (!(current[0] && event.shiftKey)) { - // If there's no current selection, or there is but Shift wasn't held, - // treat this like a single-line selection. - this.setHash(lineNumber); - return this.highlightLine(lineNumber); - } else if (event.shiftKey) { - if (lineNumber < current[0]) { - range = [lineNumber, current[0]]; - } else { - range = [current[0], lineNumber]; - } - this.setHash(range[0], range[1]); - return this.highlightRange(range); - } - }; - - LineHighlighter.prototype.clearHighlight = function() { - return $("." + this.highlightClass).removeClass(this.highlightClass); - // Unhighlight previously highlighted lines - }; - - // Convert a URL hash String into line numbers - // - // hash - Hash String - // - // Examples: - // - // hashToRange('#L5') # => [5, null] - // hashToRange('#L5-15') # => [5, 15] - // hashToRange('#foo') # => [null, null] - // - // Returns an Array - LineHighlighter.prototype.hashToRange = function(hash) { - var first, last, matches; - // ?L(\d+)(?:-(\d+))?$/) - matches = hash.match(/^#?L(\d+)(?:-(\d+))?$/); - if (matches && matches.length) { - first = parseInt(matches[1], 10); - last = matches[2] ? parseInt(matches[2], 10) : null; - return [first, last]; - } else { - return [null, null]; - } - }; - - // Highlight a single line - // - // lineNumber - Line number to highlight - LineHighlighter.prototype.highlightLine = function(lineNumber) { - return $("#LC" + lineNumber).addClass(this.highlightClass); - }; - - // Highlight all lines within a range - // - // range - Array containing the starting and ending line numbers - LineHighlighter.prototype.highlightRange = function(range) { - var i, lineNumber, ref, ref1, results; - if (range[1]) { - results = []; - for (lineNumber = i = ref = range[0], ref1 = range[1]; ref <= ref1 ? i <= ref1 : i >= ref1; lineNumber = ref <= ref1 ? (i += 1) : (i -= 1)) { - results.push(this.highlightLine(lineNumber)); - } - return results; - } else { - return this.highlightLine(range[0]); - } - }; +const LineHighlighter = function(options = {}) { + options.highlightLineClass = options.highlightLineClass || 'hll'; + options.fileHolderSelector = options.fileHolderSelector || '.file-holder'; + options.scrollFileHolder = options.scrollFileHolder || false; + options.hash = options.hash || location.hash; - // Set the URL hash string - LineHighlighter.prototype.setHash = function(firstLineNumber, lastLineNumber) { - var hash; - if (lastLineNumber) { - hash = "#L" + firstLineNumber + "-" + lastLineNumber; + this.options = options; + this._hash = options.hash; + this.highlightLineClass = options.highlightLineClass; + this.setHash = this.setHash.bind(this); + this.highlightLine = this.highlightLine.bind(this); + this.clickHandler = this.clickHandler.bind(this); + this.highlightHash = this.highlightHash.bind(this); + + this.bindEvents(); + this.highlightHash(); +}; + +LineHighlighter.prototype.bindEvents = function() { + const $fileHolder = $(this.options.fileHolderSelector); + + $fileHolder.on('click', 'a[data-line-number]', this.clickHandler); + $fileHolder.on('highlight:line', this.highlightHash); +}; + +LineHighlighter.prototype.highlightHash = function() { + var range; + + if (this._hash !== '') { + range = this.hashToRange(this._hash); + + if (range[0]) { + this.highlightRange(range); + const lineSelector = `#L${range[0]}`; + const scrollOptions = { + // Scroll to the first highlighted line on initial load + // Offset -50 for the sticky top bar, and another -100 for some context + offset: -150 + }; + if (this.options.scrollFileHolder) { + $(this.options.fileHolderSelector).scrollTo(lineSelector, scrollOptions); } else { - hash = "#L" + firstLineNumber; + $.scrollTo(lineSelector, scrollOptions); } - this._hash = hash; - return this.__setLocationHash__(hash); - }; - - // Make the actual hash change in the browser - // - // This method is stubbed in tests. - LineHighlighter.prototype.__setLocationHash__ = function(value) { - return history.pushState({ - url: value - // We're using pushState instead of assigning location.hash directly to - // prevent the page from scrolling on the hashchange event - }, document.title, value); - }; - - return LineHighlighter; - })(); -}).call(window); + } + } +}; + +LineHighlighter.prototype.clickHandler = function(event) { + var current, lineNumber, range; + event.preventDefault(); + this.clearHighlight(); + lineNumber = $(event.target).closest('a').data('line-number'); + current = this.hashToRange(this._hash); + if (!(current[0] && event.shiftKey)) { + // If there's no current selection, or there is but Shift wasn't held, + // treat this like a single-line selection. + this.setHash(lineNumber); + return this.highlightLine(lineNumber); + } else if (event.shiftKey) { + if (lineNumber < current[0]) { + range = [lineNumber, current[0]]; + } else { + range = [current[0], lineNumber]; + } + this.setHash(range[0], range[1]); + return this.highlightRange(range); + } +}; + +LineHighlighter.prototype.clearHighlight = function() { + return $("." + this.highlightLineClass).removeClass(this.highlightLineClass); +}; + +// Convert a URL hash String into line numbers +// +// hash - Hash String +// +// Examples: +// +// hashToRange('#L5') # => [5, null] +// hashToRange('#L5-15') # => [5, 15] +// hashToRange('#foo') # => [null, null] +// +// Returns an Array +LineHighlighter.prototype.hashToRange = function(hash) { + var first, last, matches; + // ?L(\d+)(?:-(\d+))?$/) + matches = hash.match(/^#?L(\d+)(?:-(\d+))?$/); + if (matches && matches.length) { + first = parseInt(matches[1], 10); + last = matches[2] ? parseInt(matches[2], 10) : null; + return [first, last]; + } else { + return [null, null]; + } +}; + +// Highlight a single line +// +// lineNumber - Line number to highlight +LineHighlighter.prototype.highlightLine = function(lineNumber) { + return $("#LC" + lineNumber).addClass(this.highlightLineClass); +}; + +// Highlight all lines within a range +// +// range - Array containing the starting and ending line numbers +LineHighlighter.prototype.highlightRange = function(range) { + var i, lineNumber, ref, ref1, results; + if (range[1]) { + results = []; + for (lineNumber = i = ref = range[0], ref1 = range[1]; ref <= ref1 ? i <= ref1 : i >= ref1; lineNumber = ref <= ref1 ? (i += 1) : (i -= 1)) { + results.push(this.highlightLine(lineNumber)); + } + return results; + } else { + return this.highlightLine(range[0]); + } +}; + +// Set the URL hash string +LineHighlighter.prototype.setHash = function(firstLineNumber, lastLineNumber) { + var hash; + if (lastLineNumber) { + hash = "#L" + firstLineNumber + "-" + lastLineNumber; + } else { + hash = "#L" + firstLineNumber; + } + this._hash = hash; + return this.__setLocationHash__(hash); +}; + +// Make the actual hash change in the browser +// +// This method is stubbed in tests. +LineHighlighter.prototype.__setLocationHash__ = function(value) { + return history.pushState({ + url: value + // We're using pushState instead of assigning location.hash directly to + // prevent the page from scrolling on the hashchange event + }, document.title, value); +}; + +window.LineHighlighter = LineHighlighter; diff --git a/app/assets/javascripts/locale/index.js b/app/assets/javascripts/locale/index.js index 7ba676d6d20..ce05b3eabec 100644 --- a/app/assets/javascripts/locale/index.js +++ b/app/assets/javascripts/locale/index.js @@ -1,29 +1,12 @@ import Jed from 'jed'; +import sprintf from './sprintf'; -/** - This is required to require all the translation folders in the current directory - this saves us having to do this manually & keep up to date with new languages -**/ -function requireAll(requireContext) { return requireContext.keys().map(requireContext); } - -const allLocales = requireAll(require.context('./', true, /^(?!.*(?:index.js$)).*\.js$/)); -const locales = allLocales.reduce((d, obj) => { - const data = d; - const localeKey = Object.keys(obj)[0]; - - data[localeKey] = obj[localeKey]; - - return data; -}, {}); - -let lang = document.querySelector('html').getAttribute('lang') || 'en'; -lang = lang.replace(/-/g, '_'); - -const locale = new Jed(locales[lang]); +const langAttribute = document.querySelector('html').getAttribute('lang'); +const lang = (langAttribute || 'en').replace(/-/g, '_'); +const locale = new Jed(window.translations || {}); /** Translates `text` - @param text The text to be translated @returns {String} The translated text **/ @@ -67,4 +50,5 @@ export { lang }; export { gettext as __ }; export { ngettext as n__ }; export { pgettext as s__ }; +export { sprintf }; export default locale; diff --git a/app/assets/javascripts/locale/sprintf.js b/app/assets/javascripts/locale/sprintf.js new file mode 100644 index 00000000000..5f4a053f98e --- /dev/null +++ b/app/assets/javascripts/locale/sprintf.js @@ -0,0 +1,26 @@ +import _ from 'underscore'; + +/** + Very limited implementation of sprintf supporting only named parameters. + + @param input (translated) text with parameters (e.g. '%{num_users} users use us') + @param parameters object mapping parameter names to values (e.g. { num_users: 5 }) + @param escapeParameters whether parameter values should be escaped (see http://underscorejs.org/#escape) + @returns {String} the text with parameters replaces (e.g. '5 users use us') + + @see https://ruby-doc.org/core-2.3.3/Kernel.html#method-i-sprintf + @see https://gitlab.com/gitlab-org/gitlab-ce/issues/37992 +**/ +export default (input, parameters, escapeParameters = true) => { + let output = input; + + if (parameters) { + Object.keys(parameters).forEach((parameterName) => { + const parameterValue = parameters[parameterName]; + const escapedParameterValue = escapeParameters ? _.escape(parameterValue) : parameterValue; + output = output.replace(new RegExp(`%{${parameterName}}`, 'g'), escapedParameterValue); + }); + } + + return output; +}; diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index ec001b9b31c..24abc5c5c9e 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -124,7 +124,6 @@ import './preview_markdown'; import './project'; import './project_avatar'; import './project_find_file'; -import './project_fork'; import './project_import'; import './project_label_subscription'; import './project_new'; @@ -302,7 +301,10 @@ $(function () { return $container.remove(); // Commit show suppressed diff }); - $('.navbar-toggle').on('click', () => $('.header-content').toggleClass('menu-expanded')); + $('.navbar-toggle').on('click', () => { + $('.header-content').toggleClass('menu-expanded'); + gl.lazyLoader.loadCheck(); + }); // Show/hide comments on diff $body.on('click', '.js-toggle-diff-comments', function (e) { var $this = $(this); diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js index 0db2abe507d..af0658eb668 100644 --- a/app/assets/javascripts/merge_request.js +++ b/app/assets/javascripts/merge_request.js @@ -127,6 +127,21 @@ import IssuablesHelper from './helpers/issuables_helper'; $el.text(gl.text.addDelimiter(count)); }; + MergeRequest.prototype.hideCloseButton = function() { + const el = document.querySelector('.merge-request .issuable-actions'); + const closeDropdownItem = el.querySelector('li.close-item'); + if (closeDropdownItem) { + closeDropdownItem.classList.add('hidden'); + // Selects the next dropdown item + el.querySelector('li.report-item').click(); + } else { + // No dropdown just hide the Close button + el.querySelector('.btn-close').classList.add('hidden'); + } + // Dropdown for mobile screen + el.querySelector('li.js-close-item').classList.add('hidden'); + }; + return MergeRequest; })(); }).call(window); diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js index 8ae127776e8..d3299c15720 100644 --- a/app/assets/javascripts/merge_request_tabs.js +++ b/app/assets/javascripts/merge_request_tabs.js @@ -352,7 +352,7 @@ import { } expandViewContainer() { - const $wrapper = $('.content-wrapper .container-fluid'); + const $wrapper = $('.content-wrapper .container-fluid').not('.breadcrumbs'); if (this.fixedLayoutPref === null) { this.fixedLayoutPref = $wrapper.hasClass('container-limited'); } diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue index f80a26b3fd4..442ed86d50c 100644 --- a/app/assets/javascripts/monitoring/components/dashboard.vue +++ b/app/assets/javascripts/monitoring/components/dashboard.vue @@ -29,6 +29,7 @@ showEmptyState: true, updateAspectRatio: false, updatedAspectRatios: 0, + hoverData: {}, resizeThrottled: {}, }; }, @@ -64,6 +65,10 @@ this.updatedAspectRatios = 0; } }, + + hoverChanged(data) { + this.hoverData = data; + }, }, created() { @@ -72,10 +77,12 @@ deploymentEndpoint: this.deploymentEndpoint, }); eventHub.$on('toggleAspectRatio', this.toggleAspectRatio); + eventHub.$on('hoverChanged', this.hoverChanged); }, beforeDestroy() { eventHub.$off('toggleAspectRatio', this.toggleAspectRatio); + eventHub.$off('hoverChanged', this.hoverChanged); window.removeEventListener('resize', this.resizeThrottled, false); }, @@ -102,6 +109,7 @@ v-for="(graphData, index) in groupData.metrics" :key="index" :graph-data="graphData" + :hover-data="hoverData" :update-aspect-ratio="updateAspectRatio" :deployment-data="store.deploymentData" /> diff --git a/app/assets/javascripts/monitoring/components/empty_state.vue b/app/assets/javascripts/monitoring/components/empty_state.vue index a7b483f6786..a18164482a2 100644 --- a/app/assets/javascripts/monitoring/components/empty_state.vue +++ b/app/assets/javascripts/monitoring/components/empty_state.vue @@ -73,34 +73,22 @@ <template> <div class="prometheus-state"> - <div class="row"> - <div class="col-md-4 col-md-offset-4 state-svg svg-content"> - <img :src="currentState.svgUrl"/> - </div> + <div class="state-svg svg-content"> + <img :src="currentState.svgUrl"/> </div> - <div class="row"> - <div class="col-md-6 col-md-offset-3"> - <h4 class="text-center state-title"> - {{currentState.title}} - </h4> - </div> - </div> - <div class="row"> - <div class="col-md-6 col-md-offset-3"> - <div class="description-text text-center state-description"> - {{currentState.description}} - <a v-if="showButtonDescription" :href="settingsPath"> - Prometheus server - </a> - </div> - </div> - </div> - <div class="row state-button-section"> - <div class="col-md-4 col-md-offset-4 text-center state-button"> - <a class="btn btn-success" :href="buttonPath"> - {{currentState.buttonText}} - </a> - </div> + <h4 class="state-title"> + {{currentState.title}} + </h4> + <p class="state-description"> + {{currentState.description}} + <a v-if="showButtonDescription" :href="settingsPath"> + Prometheus server + </a> + </p> + <div class="state-button"> + <a class="btn btn-success" :href="buttonPath"> + {{currentState.buttonText}} + </a> </div> </div> </template> diff --git a/app/assets/javascripts/monitoring/components/graph.vue b/app/assets/javascripts/monitoring/components/graph.vue index 6b3e341f936..322e083a058 100644 --- a/app/assets/javascripts/monitoring/components/graph.vue +++ b/app/assets/javascripts/monitoring/components/graph.vue @@ -7,12 +7,10 @@ import MonitoringMixin from '../mixins/monitoring_mixins'; import eventHub from '../event_hub'; import measurements from '../utils/measurements'; - import { timeScaleFormat } from '../utils/date_time_formatters'; + import { timeScaleFormat, bisectDate } from '../utils/date_time_formatters'; import createTimeSeries from '../utils/multiple_time_series'; import bp from '../../breakpoints'; - const bisectDate = d3.bisector(d => d.time).left; - export default { props: { graphData: { @@ -27,6 +25,11 @@ type: Array, required: true, }, + hoverData: { + type: Object, + required: false, + default: () => ({}), + }, }, mixins: [MonitoringMixin], @@ -52,6 +55,7 @@ currentXCoordinate: 0, currentFlagPosition: 0, showFlag: false, + showFlagContent: false, showDeployInfo: true, timeSeries: [], }; @@ -122,22 +126,14 @@ const d1 = firstTimeSeries.values[overlayIndex]; if (d0 === undefined || d1 === undefined) return; const evalTime = timeValueOverlay - d0[0] > d1[0] - timeValueOverlay; - this.currentData = evalTime ? d1 : d0; - this.currentDataIndex = evalTime ? overlayIndex : (overlayIndex - 1); - this.currentXCoordinate = Math.floor(firstTimeSeries.timeSeriesScaleX(this.currentData.time)); + const hoveredDataIndex = evalTime ? overlayIndex : (overlayIndex - 1); + const hoveredDate = firstTimeSeries.values[hoveredDataIndex].time; const currentDeployXPos = this.mouseOverDeployInfo(point.x); - if (this.currentXCoordinate > (this.graphWidth - 200)) { - this.currentFlagPosition = this.currentXCoordinate - 103; - } else { - this.currentFlagPosition = this.currentXCoordinate; - } - - if (currentDeployXPos) { - this.showFlag = false; - } else { - this.showFlag = true; - } + eventHub.$emit('hoverChanged', { + hoveredDate, + currentDeployXPos, + }); }, renderAxesPaths() { @@ -194,6 +190,10 @@ eventHub.$emit('toggleAspectRatio'); } }, + + hoverData() { + this.positionFlag(); + }, }, mounted() { @@ -203,7 +203,10 @@ </script> <template> - <div class="prometheus-graph"> + <div + class="prometheus-graph" + @mouseover="showFlagContent = true" + @mouseleave="showFlagContent = false"> <h5 class="text-center graph-title"> {{graphData.title}} </h5> @@ -257,6 +260,7 @@ :current-flag-position="currentFlagPosition" :graph-height="graphHeight" :graph-height-offset="graphHeightOffset" + :show-flag-content="showFlagContent" /> <rect class="prometheus-graph-overlay" diff --git a/app/assets/javascripts/monitoring/components/graph/flag.vue b/app/assets/javascripts/monitoring/components/graph/flag.vue index a98e3d06c18..10fb7ff6803 100644 --- a/app/assets/javascripts/monitoring/components/graph/flag.vue +++ b/app/assets/javascripts/monitoring/components/graph/flag.vue @@ -23,6 +23,10 @@ type: Number, required: true, }, + showFlagContent: { + type: Boolean, + required: true, + }, }, data() { @@ -57,6 +61,7 @@ transform="translate(-5, 20)"> </line> <svg + v-if="showFlagContent" class="rect-text-metric" :x="currentFlagPosition" y="0"> diff --git a/app/assets/javascripts/monitoring/mixins/monitoring_mixins.js b/app/assets/javascripts/monitoring/mixins/monitoring_mixins.js index 345a0b37a76..31f38aca5d6 100644 --- a/app/assets/javascripts/monitoring/mixins/monitoring_mixins.js +++ b/app/assets/javascripts/monitoring/mixins/monitoring_mixins.js @@ -1,3 +1,5 @@ +import { bisectDate } from '../utils/date_time_formatters'; + const mixins = { methods: { mouseOverDeployInfo(mouseXPos) { @@ -18,6 +20,7 @@ const mixins = { return dataFound; }, + formatDeployments() { this.reducedDeploymentData = this.deploymentData.reduce((deploymentDataArray, deployment) => { const time = new Date(deployment.created_at); @@ -40,6 +43,25 @@ const mixins = { return deploymentDataArray; }, []); }, + + positionFlag() { + const timeSeries = this.timeSeries[0]; + const hoveredDataIndex = bisectDate(timeSeries.values, this.hoverData.hoveredDate, 1); + this.currentData = timeSeries.values[hoveredDataIndex]; + this.currentDataIndex = hoveredDataIndex; + this.currentXCoordinate = Math.floor(timeSeries.timeSeriesScaleX(this.currentData.time)); + if (this.currentXCoordinate > (this.graphWidth - 200)) { + this.currentFlagPosition = this.currentXCoordinate - 103; + } else { + this.currentFlagPosition = this.currentXCoordinate; + } + + if (this.hoverData.currentDeployXPos) { + this.showFlag = false; + } else { + this.showFlag = true; + } + }, }, }; diff --git a/app/assets/javascripts/monitoring/monitoring_bundle.js b/app/assets/javascripts/monitoring/monitoring_bundle.js index ef280e02092..104432ef5de 100644 --- a/app/assets/javascripts/monitoring/monitoring_bundle.js +++ b/app/assets/javascripts/monitoring/monitoring_bundle.js @@ -3,8 +3,5 @@ import Dashboard from './components/dashboard.vue'; document.addEventListener('DOMContentLoaded', () => new Vue({ el: '#prometheus-graphs', - components: { - Dashboard, - }, - render: createElement => createElement('dashboard'), + render: createElement => createElement(Dashboard), })); diff --git a/app/assets/javascripts/monitoring/stores/monitoring_store.js b/app/assets/javascripts/monitoring/stores/monitoring_store.js index 7592af5878e..854636e9a89 100644 --- a/app/assets/javascripts/monitoring/stores/monitoring_store.js +++ b/app/assets/javascripts/monitoring/stores/monitoring_store.js @@ -13,7 +13,7 @@ function normalizeMetrics(metrics) { ...result, values: result.values.map(([timestamp, value]) => ({ time: new Date(timestamp * 1000), - value, + value: Number(value), })), })), })), diff --git a/app/assets/javascripts/monitoring/utils/date_time_formatters.js b/app/assets/javascripts/monitoring/utils/date_time_formatters.js index 26bcaa02511..c4c6b1ac1f5 100644 --- a/app/assets/javascripts/monitoring/utils/date_time_formatters.js +++ b/app/assets/javascripts/monitoring/utils/date_time_formatters.js @@ -2,6 +2,7 @@ import d3 from 'd3'; export const dateFormat = d3.time.format('%b %-d, %Y'); export const timeFormat = d3.time.format('%-I:%M%p'); +export const bisectDate = d3.bisector(d => d.time).left; export const timeScaleFormat = d3.time.format.multi([ ['.%L', d => d.getMilliseconds()], diff --git a/app/assets/javascripts/notebook/cells/code.vue b/app/assets/javascripts/notebook/cells/code.vue index b8a16356576..b4067d229aa 100644 --- a/app/assets/javascripts/notebook/cells/code.vue +++ b/app/assets/javascripts/notebook/cells/code.vue @@ -1,18 +1,3 @@ -<template> - <div class="cell"> - <code-cell - type="input" - :raw-code="rawInputCode" - :count="cell.execution_count" - :code-css-class="codeCssClass" /> - <output-cell - v-if="hasOutput" - :count="cell.execution_count" - :output="output" - :code-css-class="codeCssClass" /> - </div> -</template> - <script> import CodeCell from './code/index.vue'; import OutputCell from './output/index.vue'; @@ -51,6 +36,21 @@ export default { }; </script> +<template> + <div class="cell"> + <code-cell + type="input" + :raw-code="rawInputCode" + :count="cell.execution_count" + :code-css-class="codeCssClass" /> + <output-cell + v-if="hasOutput" + :count="cell.execution_count" + :output="output" + :code-css-class="codeCssClass" /> + </div> +</template> + <style scoped> .cell { flex-direction: column; diff --git a/app/assets/javascripts/notebook/cells/code/index.vue b/app/assets/javascripts/notebook/cells/code/index.vue index 31b30f601e2..0f3083f05b2 100644 --- a/app/assets/javascripts/notebook/cells/code/index.vue +++ b/app/assets/javascripts/notebook/cells/code/index.vue @@ -1,17 +1,3 @@ -<template> - <div :class="type"> - <prompt - :type="promptType" - :count="count" /> - <pre - class="language-python" - :class="codeCssClass" - ref="code" - v-text="code"> - </pre> - </div> -</template> - <script> import Prism from '../../lib/highlight'; import Prompt from '../prompt.vue'; @@ -55,3 +41,17 @@ }, }; </script> + +<template> + <div :class="type"> + <prompt + :type="promptType" + :count="count" /> + <pre + class="language-python" + :class="codeCssClass" + ref="code" + v-text="code"> + </pre> + </div> +</template> diff --git a/app/assets/javascripts/notebook/cells/markdown.vue b/app/assets/javascripts/notebook/cells/markdown.vue index 814d2ea92b4..82c51a1068c 100644 --- a/app/assets/javascripts/notebook/cells/markdown.vue +++ b/app/assets/javascripts/notebook/cells/markdown.vue @@ -1,10 +1,3 @@ -<template> - <div class="cell text-cell"> - <prompt /> - <div class="markdown" v-html="markdown"></div> - </div> -</template> - <script> /* global katex */ import marked from 'marked'; @@ -95,6 +88,13 @@ }; </script> +<template> + <div class="cell text-cell"> + <prompt /> + <div class="markdown" v-html="markdown"></div> + </div> +</template> + <style> .markdown .katex { display: block; diff --git a/app/assets/javascripts/notebook/cells/output/html.vue b/app/assets/javascripts/notebook/cells/output/html.vue index 0f39cd138df..2110a9de7ed 100644 --- a/app/assets/javascripts/notebook/cells/output/html.vue +++ b/app/assets/javascripts/notebook/cells/output/html.vue @@ -1,10 +1,3 @@ -<template> - <div class="output"> - <prompt /> - <div v-html="rawCode"></div> - </div> -</template> - <script> import Prompt from '../prompt.vue'; @@ -20,3 +13,10 @@ export default { }, }; </script> + +<template> + <div class="output"> + <prompt /> + <div v-html="rawCode"></div> + </div> +</template> diff --git a/app/assets/javascripts/notebook/cells/output/image.vue b/app/assets/javascripts/notebook/cells/output/image.vue index f3b873bbc0f..fbb39ea6e2d 100644 --- a/app/assets/javascripts/notebook/cells/output/image.vue +++ b/app/assets/javascripts/notebook/cells/output/image.vue @@ -1,11 +1,3 @@ -<template> - <div class="output"> - <prompt /> - <img - :src="'data:' + outputType + ';base64,' + rawCode" /> - </div> -</template> - <script> import Prompt from '../prompt.vue'; @@ -25,3 +17,11 @@ export default { }, }; </script> + +<template> + <div class="output"> + <prompt /> + <img + :src="'data:' + outputType + ';base64,' + rawCode" /> + </div> +</template> diff --git a/app/assets/javascripts/notebook/cells/output/index.vue b/app/assets/javascripts/notebook/cells/output/index.vue index 23c9ea78939..05af0bf1e8e 100644 --- a/app/assets/javascripts/notebook/cells/output/index.vue +++ b/app/assets/javascripts/notebook/cells/output/index.vue @@ -1,12 +1,3 @@ -<template> - <component :is="componentName" - type="output" - :outputType="outputType" - :count="count" - :raw-code="rawCode" - :code-css-class="codeCssClass" /> -</template> - <script> import CodeCell from '../code/index.vue'; import Html from './html.vue'; @@ -81,3 +72,12 @@ export default { }, }; </script> + +<template> + <component :is="componentName" + type="output" + :outputType="outputType" + :count="count" + :raw-code="rawCode" + :code-css-class="codeCssClass" /> +</template> diff --git a/app/assets/javascripts/notebook/cells/prompt.vue b/app/assets/javascripts/notebook/cells/prompt.vue index 4540e4248d8..039fb99293d 100644 --- a/app/assets/javascripts/notebook/cells/prompt.vue +++ b/app/assets/javascripts/notebook/cells/prompt.vue @@ -1,11 +1,3 @@ -<template> - <div class="prompt"> - <span v-if="type && count"> - {{ type }} [{{ count }}]: - </span> - </div> -</template> - <script> export default { props: { @@ -21,6 +13,14 @@ }; </script> +<template> + <div class="prompt"> + <span v-if="type && count"> + {{ type }} [{{ count }}]: + </span> + </div> +</template> + <style scoped> .prompt { padding: 0 10px; diff --git a/app/assets/javascripts/notebook/index.vue b/app/assets/javascripts/notebook/index.vue index fd62c1231ef..e88806431af 100644 --- a/app/assets/javascripts/notebook/index.vue +++ b/app/assets/javascripts/notebook/index.vue @@ -1,14 +1,3 @@ -<template> - <div v-if="hasNotebook"> - <component - v-for="(cell, index) in cells" - :is="cellType(cell.cell_type)" - :cell="cell" - :key="index" - :code-css-class="codeCssClass" /> - </div> -</template> - <script> import { MarkdownCell, @@ -59,6 +48,17 @@ }; </script> +<template> + <div v-if="hasNotebook"> + <component + v-for="(cell, index) in cells" + :is="cellType(cell.cell_type)" + :cell="cell" + :key="index" + :code-css-class="codeCssClass" /> + </div> +</template> + <style> .cell, .input, diff --git a/app/assets/javascripts/notes/components/issue_comment_form.vue b/app/assets/javascripts/notes/components/issue_comment_form.vue index fa7ac994058..1a7da84a424 100644 --- a/app/assets/javascripts/notes/components/issue_comment_form.vue +++ b/app/assets/javascripts/notes/components/issue_comment_form.vue @@ -272,6 +272,7 @@ v-model="note" ref="textarea" slot="textarea" + :disabled="isSubmitting" placeholder="Write a comment or drag your files here..." @keydown.up="editCurrentUserLastNote()" @keydown.meta.enter="handleSave()"> diff --git a/app/assets/javascripts/notes/components/issue_note.vue b/app/assets/javascripts/notes/components/issue_note.vue index 3483f6c7538..1f43b8a16ad 100644 --- a/app/assets/javascripts/notes/components/issue_note.vue +++ b/app/assets/javascripts/notes/components/issue_note.vue @@ -62,7 +62,7 @@ }, deleteHandler() { // eslint-disable-next-line no-alert - if (confirm('Are you sure you want to delete this list?')) { + if (confirm('Are you sure you want to delete this comment?')) { this.isDeleting = true; this.deleteNote(this.note) diff --git a/app/assets/javascripts/pdf/index.vue b/app/assets/javascripts/pdf/index.vue index b874e484d45..c8a2f778ee8 100644 --- a/app/assets/javascripts/pdf/index.vue +++ b/app/assets/javascripts/pdf/index.vue @@ -1,13 +1,3 @@ -<template> - <div class="pdf-viewer" v-if="hasPDF"> - <page v-for="(page, index) in pages" - :key="index" - :v-if="!loading" - :page="page" - :number="index + 1" /> - </div> -</template> - <script> import pdfjsLib from 'vendor/pdf'; import workerSrc from 'vendor/pdf.worker.min'; @@ -64,6 +54,16 @@ }; </script> +<template> + <div class="pdf-viewer" v-if="hasPDF"> + <page v-for="(page, index) in pages" + :key="index" + :v-if="!loading" + :page="page" + :number="index + 1" /> + </div> +</template> + <style> .pdf-viewer { background: url('./assets/img/bg.gif'); diff --git a/app/assets/javascripts/pdf/page/index.vue b/app/assets/javascripts/pdf/page/index.vue index 7b74ee4eb2e..be38f7cc129 100644 --- a/app/assets/javascripts/pdf/page/index.vue +++ b/app/assets/javascripts/pdf/page/index.vue @@ -1,10 +1,3 @@ -<template> - <canvas - class="pdf-page" - ref="canvas" - :data-page="number" /> -</template> - <script> export default { props: { @@ -48,6 +41,13 @@ }; </script> +<template> + <canvas + class="pdf-page" + ref="canvas" + :data-page="number" /> +</template> + <style> .pdf-page { margin: 8px auto 0 auto; diff --git a/app/assets/javascripts/pipelines/components/pipeline_url.vue b/app/assets/javascripts/pipelines/components/pipeline_url.vue index f0b44dfa6d8..76b97af39f1 100644 --- a/app/assets/javascripts/pipelines/components/pipeline_url.vue +++ b/app/assets/javascripts/pipelines/components/pipeline_url.vue @@ -28,8 +28,7 @@ popoverOptions() { return { html: true, - delay: { hide: 600 }, - trigger: 'hover', + trigger: 'focus', placement: 'top', title: '<div class="autodevops-title">This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b></div>', content: `<a class="autodevops-link" href="${this.autoDevopsHelpPath}" target="_blank" rel="noopener noreferrer nofollow">Learn more about Auto DevOps</a>`, @@ -75,6 +74,7 @@ </span> <a v-if="pipeline.flags.auto_devops" + tabindex="0" class="js-pipeline-url-autodevops label label-info autodevops-badge" v-popover="popoverOptions" role="button"> diff --git a/app/assets/javascripts/pipelines/mixins/pipelines.js b/app/assets/javascripts/pipelines/mixins/pipelines.js index 9adc15e6266..e97f5632dc8 100644 --- a/app/assets/javascripts/pipelines/mixins/pipelines.js +++ b/app/assets/javascripts/pipelines/mixins/pipelines.js @@ -97,7 +97,7 @@ export default { postAction(endpoint) { this.service.postAction(endpoint) .then(() => eventHub.$emit('refreshPipelines')) - .catch(() => new Flash('An error occured while making the request.')); + .catch(() => new Flash('An error occurred while making the request.')); }, }, }; diff --git a/app/assets/javascripts/profile/gl_crop.js b/app/assets/javascripts/profile/gl_crop.js index 291ae24aa68..4bdda611cfc 100644 --- a/app/assets/javascripts/profile/gl_crop.js +++ b/app/assets/javascripts/profile/gl_crop.js @@ -73,7 +73,8 @@ import _ from 'underscore'; aspectRatio: 1, modal: true, scalable: false, - rotatable: false, + rotatable: true, + checkOrientation: true, zoomable: true, dragMode: 'move', guides: false, diff --git a/app/assets/javascripts/project_fork.js b/app/assets/javascripts/project_fork.js index 47197db39d3..65d46fa9a73 100644 --- a/app/assets/javascripts/project_fork.js +++ b/app/assets/javascripts/project_fork.js @@ -1,13 +1,7 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, prefer-arrow-callback, max-len */ -(function() { - this.ProjectFork = (function() { - function ProjectFork() { - $('.fork-thumbnail a').on('click', function() { - $('.fork-namespaces').hide(); - return $('.save-project-loader').show(); - }); - } +export default () => { + $('.js-fork-thumbnail').on('click', function forkThumbnailClicked() { + if ($(this).hasClass('disabled')) return false; - return ProjectFork; - })(); -}).call(window); + return $('.js-fork-content').toggle(); + }); +}; diff --git a/app/assets/javascripts/projects_dropdown/service/projects_service.js b/app/assets/javascripts/projects_dropdown/service/projects_service.js index fad956b4c26..9cbd8f21f2a 100644 --- a/app/assets/javascripts/projects_dropdown/service/projects_service.js +++ b/app/assets/javascripts/projects_dropdown/service/projects_service.js @@ -19,7 +19,7 @@ export default class ProjectsService { getSearchedProjects(searchQuery) { return this.projectsPath.get({ - simple: false, + simple: true, per_page: 20, membership: !!gon.current_user_id, order_by: 'last_activity_at', diff --git a/app/assets/javascripts/registry/components/app.vue b/app/assets/javascripts/registry/components/app.vue new file mode 100644 index 00000000000..2d8ca443ea7 --- /dev/null +++ b/app/assets/javascripts/registry/components/app.vue @@ -0,0 +1,62 @@ +<script> + /* globals Flash */ + import { mapGetters, mapActions } from 'vuex'; + import '../../flash'; + import loadingIcon from '../../vue_shared/components/loading_icon.vue'; + import store from '../stores'; + import collapsibleContainer from './collapsible_container.vue'; + import { errorMessages, errorMessagesTypes } from '../constants'; + + export default { + name: 'registryListApp', + props: { + endpoint: { + type: String, + required: true, + }, + }, + store, + components: { + collapsibleContainer, + loadingIcon, + }, + computed: { + ...mapGetters([ + 'isLoading', + 'repos', + ]), + }, + methods: { + ...mapActions([ + 'setMainEndpoint', + 'fetchRepos', + ]), + }, + created() { + this.setMainEndpoint(this.endpoint); + }, + mounted() { + this.fetchRepos() + .catch(() => Flash(errorMessages[errorMessagesTypes.FETCH_REPOS])); + }, + }; +</script> +<template> + <div> + <loading-icon + v-if="isLoading" + size="3" + /> + + <collapsible-container + v-else-if="!isLoading && repos.length" + v-for="(item, index) in repos" + :key="index" + :repo="item" + /> + + <p v-else-if="!isLoading && !repos.length"> + {{__("No container images stored for this project. Add one by following the instructions above.")}} + </p> + </div> +</template> diff --git a/app/assets/javascripts/registry/components/collapsible_container.vue b/app/assets/javascripts/registry/components/collapsible_container.vue new file mode 100644 index 00000000000..41ea9742406 --- /dev/null +++ b/app/assets/javascripts/registry/components/collapsible_container.vue @@ -0,0 +1,131 @@ +<script> + /* globals Flash */ + import { mapActions } from 'vuex'; + import '../../flash'; + import clipboardButton from '../../vue_shared/components/clipboard_button.vue'; + import loadingIcon from '../../vue_shared/components/loading_icon.vue'; + import tooltip from '../../vue_shared/directives/tooltip'; + import tableRegistry from './table_registry.vue'; + import { errorMessages, errorMessagesTypes } from '../constants'; + + export default { + name: 'collapsibeContainerRegisty', + props: { + repo: { + type: Object, + required: true, + }, + }, + components: { + clipboardButton, + loadingIcon, + tableRegistry, + }, + directives: { + tooltip, + }, + data() { + return { + isOpen: false, + }; + }, + computed: { + clipboardText() { + return `docker pull ${this.repo.location}`; + }, + }, + methods: { + ...mapActions([ + 'fetchRepos', + 'fetchList', + 'deleteRepo', + ]), + + toggleRepo() { + this.isOpen = !this.isOpen; + + if (this.isOpen) { + this.fetchList({ repo: this.repo }) + .catch(() => this.showError(errorMessagesTypes.FETCH_REGISTRY)); + } + }, + + handleDeleteRepository() { + this.deleteRepo(this.repo) + .then(() => this.fetchRepos()) + .catch(() => this.showError(errorMessagesTypes.DELETE_REPO)); + }, + + showError(message) { + Flash((errorMessages[message])); + }, + }, + }; +</script> + +<template> + <div class="container-image"> + <div + class="container-image-head"> + <button + type="button" + @click="toggleRepo" + class="js-toggle-repo btn-link"> + <i + class="fa" + :class="{ + 'fa-chevron-right': !isOpen, + 'fa-chevron-up': isOpen, + }" + aria-hidden="true"> + </i> + {{repo.name}} + </button> + + <clipboard-button + v-if="repo.location" + :text="clipboardText" + :title="repo.location" + /> + + <div class="controls hidden-xs pull-right"> + <button + v-if="repo.canDelete" + type="button" + class="js-remove-repo btn btn-danger" + :title="s__('ContainerRegistry|Remove repository')" + :aria-label="s__('ContainerRegistry|Remove repository')" + v-tooltip + @click="handleDeleteRepository"> + <i + class="fa fa-trash" + aria-hidden="true"> + </i> + </button> + </div> + + </div> + + <loading-icon + v-if="repo.isLoading" + class="append-bottom-20" + size="2" + /> + + <div + v-else-if="!repo.isLoading && isOpen" + class="container-image-tags"> + + <table-registry + v-if="repo.list.length" + :repo="repo" + /> + + <div + v-else + class="nothing-here-block"> + {{s__("ContainerRegistry|No tags in Container Registry for this container image.")}} + </div> + </div> + </div> +</template> diff --git a/app/assets/javascripts/registry/components/table_registry.vue b/app/assets/javascripts/registry/components/table_registry.vue new file mode 100644 index 00000000000..4ce1571b0aa --- /dev/null +++ b/app/assets/javascripts/registry/components/table_registry.vue @@ -0,0 +1,137 @@ +<script> + /* globals Flash */ + import { mapActions } from 'vuex'; + import { n__ } from '../../locale'; + import '../../flash'; + import clipboardButton from '../../vue_shared/components/clipboard_button.vue'; + import tablePagination from '../../vue_shared/components/table_pagination.vue'; + import tooltip from '../../vue_shared/directives/tooltip'; + import timeagoMixin from '../../vue_shared/mixins/timeago'; + import { errorMessages, errorMessagesTypes } from '../constants'; + + export default { + props: { + repo: { + type: Object, + required: true, + }, + }, + components: { + clipboardButton, + tablePagination, + }, + mixins: [ + timeagoMixin, + ], + directives: { + tooltip, + }, + computed: { + shouldRenderPagination() { + return this.repo.pagination.total > this.repo.pagination.perPage; + }, + }, + methods: { + ...mapActions([ + 'fetchList', + 'deleteRegistry', + ]), + + layers(item) { + return item.layers ? n__('%d layer', '%d layers', item.layers) : ''; + }, + + handleDeleteRegistry(registry) { + this.deleteRegistry(registry) + .then(() => this.fetchList({ repo: this.repo })) + .catch(() => this.showError(errorMessagesTypes.DELETE_REGISTRY)); + }, + + onPageChange(pageNumber) { + this.fetchList({ repo: this.repo, page: pageNumber }) + .catch(() => this.showError(errorMessagesTypes.FETCH_REGISTRY)); + }, + + clipboardText(text) { + return `docker pull ${text}`; + }, + + showError(message) { + Flash((errorMessages[message])); + }, + }, + }; +</script> +<template> +<div> + <table class="table tags"> + <thead> + <tr> + <th>{{s__('ContainerRegistry|Tag')}}</th> + <th>{{s__('ContainerRegistry|Tag ID')}}</th> + <th>{{s__("ContainerRegistry|Size")}}</th> + <th>{{s__("ContainerRegistry|Created")}}</th> + <th></th> + </tr> + </thead> + <tbody> + <tr + v-for="(item, i) in repo.list" + :key="i"> + <td> + + {{item.tag}} + + <clipboard-button + v-if="item.location" + :title="item.location" + :text="clipboardText(item.location)" + /> + </td> + <td> + <span + v-tooltip + :title="item.revision" + data-placement="bottom"> + {{item.shortRevision}} + </span> + </td> + <td> + {{item.size}} + <template v-if="item.size && item.layers"> + · + </template> + {{layers(item)}} + </td> + + <td> + {{timeFormated(item.createdAt)}} + </td> + + <td class="content"> + <button + v-if="item.canDelete" + type="button" + class="js-delete-registry btn btn-danger hidden-xs pull-right" + :title="s__('ContainerRegistry|Remove tag')" + :aria-label="s__('ContainerRegistry|Remove tag')" + data-container="body" + v-tooltip + @click="handleDeleteRegistry(item)"> + <i + class="fa fa-trash" + aria-hidden="true"> + </i> + </button> + </td> + </tr> + </tbody> + </table> + + <table-pagination + v-if="shouldRenderPagination" + :change="onPageChange" + :page-info="repo.pagination" + /> +</div> +</template> diff --git a/app/assets/javascripts/registry/constants.js b/app/assets/javascripts/registry/constants.js new file mode 100644 index 00000000000..712b0fade3d --- /dev/null +++ b/app/assets/javascripts/registry/constants.js @@ -0,0 +1,15 @@ +import { __ } from '../locale'; + +export const errorMessagesTypes = { + FETCH_REGISTRY: 'FETCH_REGISTRY', + FETCH_REPOS: 'FETCH_REPOS', + DELETE_REPO: 'DELETE_REPO', + DELETE_REGISTRY: 'DELETE_REGISTRY', +}; + +export const errorMessages = { + [errorMessagesTypes.FETCH_REGISTRY]: __('Something went wrong while fetching the registry list.'), + [errorMessagesTypes.FETCH_REPOS]: __('Something went wrong while fetching the projects.'), + [errorMessagesTypes.DELETE_REPO]: __('Something went wrong on our end.'), + [errorMessagesTypes.DELETE_REGISTRY]: __('Something went wrong on our end.'), +}; diff --git a/app/assets/javascripts/registry/index.js b/app/assets/javascripts/registry/index.js new file mode 100644 index 00000000000..d8edff73f72 --- /dev/null +++ b/app/assets/javascripts/registry/index.js @@ -0,0 +1,25 @@ +import Vue from 'vue'; +import registryApp from './components/app.vue'; +import Translate from '../vue_shared/translate'; + +Vue.use(Translate); + +document.addEventListener('DOMContentLoaded', () => new Vue({ + el: '#js-vue-registry-images', + components: { + registryApp, + }, + data() { + const dataset = document.querySelector(this.$options.el).dataset; + return { + endpoint: dataset.endpoint, + }; + }, + render(createElement) { + return createElement('registry-app', { + props: { + endpoint: this.endpoint, + }, + }); + }, +})); diff --git a/app/assets/javascripts/registry/stores/actions.js b/app/assets/javascripts/registry/stores/actions.js new file mode 100644 index 00000000000..34ed40b8b65 --- /dev/null +++ b/app/assets/javascripts/registry/stores/actions.js @@ -0,0 +1,39 @@ +import Vue from 'vue'; +import VueResource from 'vue-resource'; +import * as types from './mutation_types'; + +Vue.use(VueResource); + +export const fetchRepos = ({ commit, state }) => { + commit(types.TOGGLE_MAIN_LOADING); + + return Vue.http.get(state.endpoint) + .then(res => res.json()) + .then((response) => { + commit(types.TOGGLE_MAIN_LOADING); + commit(types.SET_REPOS_LIST, response); + }); +}; + +export const fetchList = ({ commit }, { repo, page }) => { + commit(types.TOGGLE_REGISTRY_LIST_LOADING, repo); + + return Vue.http.get(repo.tagsPath, { params: { page } }) + .then((response) => { + const headers = response.headers; + + return response.json().then((resp) => { + commit(types.TOGGLE_REGISTRY_LIST_LOADING, repo); + commit(types.SET_REGISTRY_LIST, { repo, resp, headers }); + }); + }); +}; + +export const deleteRepo = ({ commit }, repo) => Vue.http.delete(repo.destroyPath) + .then(res => res.json()); + +export const deleteRegistry = ({ commit }, image) => Vue.http.delete(image.destroyPath) + .then(res => res.json()); + +export const setMainEndpoint = ({ commit }, data) => commit(types.SET_MAIN_ENDPOINT, data); +export const toggleLoading = ({ commit }) => commit(types.TOGGLE_MAIN_LOADING); diff --git a/app/assets/javascripts/registry/stores/getters.js b/app/assets/javascripts/registry/stores/getters.js new file mode 100644 index 00000000000..588f479c492 --- /dev/null +++ b/app/assets/javascripts/registry/stores/getters.js @@ -0,0 +1,2 @@ +export const isLoading = state => state.isLoading; +export const repos = state => state.repos; diff --git a/app/assets/javascripts/registry/stores/index.js b/app/assets/javascripts/registry/stores/index.js new file mode 100644 index 00000000000..78b67881210 --- /dev/null +++ b/app/assets/javascripts/registry/stores/index.js @@ -0,0 +1,39 @@ +import Vue from 'vue'; +import Vuex from 'vuex'; +import * as actions from './actions'; +import * as getters from './getters'; +import mutations from './mutations'; + +Vue.use(Vuex); + +export default new Vuex.Store({ + state: { + isLoading: false, + endpoint: '', // initial endpoint to fetch the repos list + /** + * Each object in `repos` has the following strucure: + * { + * name: String, + * isLoading: Boolean, + * tagsPath: String // endpoint to request the list + * destroyPath: String // endpoit to delete the repo + * list: Array // List of the registry images + * } + * + * Each registry image inside `list` has the following structure: + * { + * tag: String, + * revision: String + * shortRevision: String + * size: Number + * layers: Number + * createdAt: String + * destroyPath: String // endpoit to delete each image + * } + */ + repos: [], + }, + actions, + getters, + mutations, +}); diff --git a/app/assets/javascripts/registry/stores/mutation_types.js b/app/assets/javascripts/registry/stores/mutation_types.js new file mode 100644 index 00000000000..2c69bf11807 --- /dev/null +++ b/app/assets/javascripts/registry/stores/mutation_types.js @@ -0,0 +1,7 @@ +export const SET_MAIN_ENDPOINT = 'SET_MAIN_ENDPOINT'; + +export const SET_REPOS_LIST = 'SET_REPOS_LIST'; +export const TOGGLE_MAIN_LOADING = 'TOGGLE_MAIN_LOADING'; + +export const SET_REGISTRY_LIST = 'SET_REGISTRY_LIST'; +export const TOGGLE_REGISTRY_LIST_LOADING = 'TOGGLE_REGISTRY_LIST_LOADING'; diff --git a/app/assets/javascripts/registry/stores/mutations.js b/app/assets/javascripts/registry/stores/mutations.js new file mode 100644 index 00000000000..e40382e7afc --- /dev/null +++ b/app/assets/javascripts/registry/stores/mutations.js @@ -0,0 +1,54 @@ +import * as types from './mutation_types'; +import { parseIntPagination, normalizeHeaders } from '../../lib/utils/common_utils'; + +export default { + + [types.SET_MAIN_ENDPOINT](state, endpoint) { + Object.assign(state, { endpoint }); + }, + + [types.SET_REPOS_LIST](state, list) { + Object.assign(state, { + repos: list.map(el => ({ + canDelete: !!el.destroy_path, + destroyPath: el.destroy_path, + id: el.id, + isLoading: false, + list: [], + location: el.location, + name: el.path, + tagsPath: el.tags_path, + })), + }); + }, + + [types.TOGGLE_MAIN_LOADING](state) { + Object.assign(state, { isLoading: !state.isLoading }); + }, + + [types.SET_REGISTRY_LIST](state, { repo, resp, headers }) { + const listToUpdate = state.repos.find(el => el.id === repo.id); + + const normalizedHeaders = normalizeHeaders(headers); + const pagination = parseIntPagination(normalizedHeaders); + + listToUpdate.pagination = pagination; + + listToUpdate.list = resp.map(element => ({ + tag: element.name, + revision: element.revision, + shortRevision: element.short_revision, + size: element.size, + layers: element.layers, + location: element.location, + createdAt: element.created_at, + destroyPath: element.destroy_path, + canDelete: !!element.destroy_path, + })); + }, + + [types.TOGGLE_REGISTRY_LIST_LOADING](state, list) { + const listToUpdate = state.repos.find(el => el.id === list.id); + listToUpdate.isLoading = !listToUpdate.isLoading; + }, +}; diff --git a/app/assets/javascripts/repo/components/repo_commit_section.vue b/app/assets/javascripts/repo/components/repo_commit_section.vue index 1282828b504..119e38c583d 100644 --- a/app/assets/javascripts/repo/components/repo_commit_section.vue +++ b/app/assets/javascripts/repo/components/repo_commit_section.vue @@ -37,14 +37,14 @@ export default { content: f.newContent, })); const payload = { - branch: Store.targetBranch, + branch: Store.currentBranch, commit_message: commitMessage, actions, }; Store.submitCommitsLoading = true; Service.commitFiles(payload) .then(this.resetCommitState) - .catch(() => Flash('An error occured while committing your changes')); + .catch(() => Flash('An error occurred while committing your changes')); }, resetCommitState() { @@ -105,7 +105,7 @@ export default { </label> <div class="col-md-6"> <span class="help-block"> - {{targetBranch}} + {{currentBranch}} </span> </div> </div> diff --git a/app/assets/javascripts/repo/components/repo_edit_button.vue b/app/assets/javascripts/repo/components/repo_edit_button.vue index 29b76975561..353142edeb7 100644 --- a/app/assets/javascripts/repo/components/repo_edit_button.vue +++ b/app/assets/javascripts/repo/components/repo_edit_button.vue @@ -26,16 +26,6 @@ export default { this.editMode = !this.editMode; Store.toggleBlobView(); }, - toggleProjectRefsForm() { - $('.project-refs-form').toggleClass('disabled', this.editMode); - $('.js-tree-ref-target-holder').toggle(this.editMode); - }, - }, - - watch: { - editMode() { - this.toggleProjectRefsForm(); - }, }, }; </script> diff --git a/app/assets/javascripts/repo/components/repo_file.vue b/app/assets/javascripts/repo/components/repo_file.vue index 20ebf840774..8b9cbd23456 100644 --- a/app/assets/javascripts/repo/components/repo_file.vue +++ b/app/assets/javascripts/repo/components/repo_file.vue @@ -95,7 +95,7 @@ export default RepoFile; </div> </td> - <td class="hidden-xs"> + <td class="hidden-xs text-right"> <span class="commit-update" :title="tooltipTitle(file.lastCommitUpdate)"> diff --git a/app/assets/javascripts/repo/components/repo_preview.vue b/app/assets/javascripts/repo/components/repo_preview.vue index 2200754cbef..2fe369a4693 100644 --- a/app/assets/javascripts/repo/components/repo_preview.vue +++ b/app/assets/javascripts/repo/components/repo_preview.vue @@ -1,23 +1,27 @@ <script> +/* global LineHighlighter */ + import Store from '../stores/repo_store'; export default { data: () => Store, - mounted() { - this.highlightFile(); - }, computed: { html() { return this.activeFile.html; }, }, - methods: { highlightFile() { $(this.$el).find('.file-content').syntaxHighlight(); }, }, - + mounted() { + this.highlightFile(); + this.lineHighlighter = new LineHighlighter({ + fileHolderSelector: '.blob-viewer-container', + scrollFileHolder: true, + }); + }, watch: { html() { this.$nextTick(() => { @@ -45,7 +49,7 @@ export default { v-else class="vertical-center render-error"> <p class="text-center"> - The source could not be displayed because a rendering error occured. You can <a :href="activeFile.raw_path">download</a> it instead. + The source could not be displayed because a rendering error occurred. You can <a :href="activeFile.raw_path">download</a> it instead. </p> </div> </div> diff --git a/app/assets/javascripts/repo/components/repo_sidebar.vue b/app/assets/javascripts/repo/components/repo_sidebar.vue index 3414128526d..685f6ff806f 100644 --- a/app/assets/javascripts/repo/components/repo_sidebar.vue +++ b/app/assets/javascripts/repo/components/repo_sidebar.vue @@ -37,17 +37,24 @@ export default { let file = clickedFile; if (file.loading) return; file.loading = true; + if (file.type === 'tree' && file.opened) { file = Store.removeChildFilesOfTree(file); file.loading = false; } else { - Service.url = file.url; - Helper.getContent(file) - .then(() => { - file.loading = false; - Helper.scrollTabsRight(); - }) - .catch(Helper.loadingError); + const openFile = Helper.getFileFromPath(file.url); + if (openFile) { + file.loading = false; + Store.setActiveFiles(openFile); + } else { + Service.url = file.url; + Helper.getContent(file) + .then(() => { + file.loading = false; + Helper.scrollTabsRight(); + }) + .catch(Helper.loadingError); + } } }, @@ -67,8 +74,8 @@ export default { <thead v-if="!isMini"> <tr> <th class="name">Name</th> - <th class="hidden-sm hidden-xs last-commit">Last Commit</th> - <th class="hidden-xs last-update">Last Update</th> + <th class="hidden-sm hidden-xs last-commit">Last commit</th> + <th class="hidden-xs last-update text-right">Last update</th> </tr> </thead> <tbody> diff --git a/app/assets/javascripts/repo/helpers/repo_helper.js b/app/assets/javascripts/repo/helpers/repo_helper.js index 2bd8d7eea65..ac59a2bed23 100644 --- a/app/assets/javascripts/repo/helpers/repo_helper.js +++ b/app/assets/javascripts/repo/helpers/repo_helper.js @@ -58,13 +58,13 @@ const RepoHelper = { return langs.find(lang => lang.extensions && lang.extensions.indexOf(`.${ext}`) > -1); }, - setDirectoryOpen(tree) { + setDirectoryOpen(tree, title) { const file = tree; if (!file) return undefined; file.opened = true; file.icon = 'fa-folder-open'; - RepoHelper.updateHistoryEntry(file.url, file.name); + RepoHelper.updateHistoryEntry(file.url, title); return file; }, @@ -135,6 +135,8 @@ const RepoHelper = { return Service.getContent() .then((response) => { const data = response.data; + if (response.headers && response.headers['page-title']) data.pageTitle = response.headers['page-title']; + Store.isTree = RepoHelper.isTree(data); if (!Store.isTree) { if (!file) file = data; @@ -168,7 +170,7 @@ const RepoHelper = { } else { // it's a tree if (!file) Store.isRoot = RepoHelper.isRoot(Service.url); - file = RepoHelper.setDirectoryOpen(file); + file = RepoHelper.setDirectoryOpen(file, data.pageTitle || data.name); const newDirectory = RepoHelper.dataToListOfFiles(data); Store.addFilesToDirectory(file, Store.files, newDirectory); Store.prevURL = Service.blobURLtoParentTree(Service.url); @@ -178,8 +180,8 @@ const RepoHelper = { setFile(data, file) { const newFile = data; + newFile.url = file.url || Service.url; // Grab the URL from service, happens on page refresh. - newFile.url = file.url; if (newFile.render_error === 'too_large' || newFile.render_error === 'collapsed') { newFile.tooLarge = true; } @@ -255,7 +257,7 @@ const RepoHelper = { history.pushState({ key: RepoHelper.key }, '', url); if (title) { - document.title = `${title} · GitLab`; + document.title = title; } }, @@ -263,6 +265,10 @@ const RepoHelper = { return Store.openedFiles.find(openedFile => Store.activeFile.url === openedFile.url); }, + getFileFromPath(path) { + return Store.openedFiles.find(file => file.url === path); + }, + loadingError() { Flash('Unable to load this content at this time.'); }, diff --git a/app/assets/javascripts/repo/index.js b/app/assets/javascripts/repo/index.js index 6c1d468e937..7d0123e3d3a 100644 --- a/app/assets/javascripts/repo/index.js +++ b/app/assets/javascripts/repo/index.js @@ -11,10 +11,6 @@ function initDropdowns() { } function addEventsForNonVueEls() { - $(document).on('change', '.dropdown', () => { - Store.targetBranch = $('.project-refs-target-form input[name="ref"]').val(); - }); - window.onbeforeunload = function confirmUnload(e) { const hasChanged = Store.openedFiles .some(file => file.changed); diff --git a/app/assets/javascripts/repo/stores/repo_store.js b/app/assets/javascripts/repo/stores/repo_store.js index 1c0df528aea..9a4fc40bc69 100644 --- a/app/assets/javascripts/repo/stores/repo_store.js +++ b/app/assets/javascripts/repo/stores/repo_store.js @@ -32,7 +32,6 @@ const RepoStore = { isCommitable: false, binary: false, currentBranch: '', - targetBranch: 'new-branch', commitMessage: '', binaryTypes: { png: false, @@ -84,7 +83,7 @@ const RepoStore = { }).catch(Helper.loadingError); } - if (!file.loading) Helper.updateHistoryEntry(file.url, file.name); + if (!file.loading) Helper.updateHistoryEntry(file.url, file.pageTitle || file.name); RepoStore.binary = file.binary; }, diff --git a/app/assets/javascripts/right_sidebar.js b/app/assets/javascripts/right_sidebar.js index a4eae135403..a41548bd694 100644 --- a/app/assets/javascripts/right_sidebar.js +++ b/app/assets/javascripts/right_sidebar.js @@ -29,28 +29,32 @@ import Cookies from 'js-cookie'; $('.dropdown').on('loading.gl.dropdown', this.sidebarDropdownLoading); $('.dropdown').on('loaded.gl.dropdown', this.sidebarDropdownLoaded); - $document.on('click', '.js-sidebar-toggle', function(e, triggered) { - var $allGutterToggleIcons, $this, $thisIcon; - e.preventDefault(); - $this = $(this); - $thisIcon = $this.find('i'); - $allGutterToggleIcons = $('.js-sidebar-toggle i'); - if ($thisIcon.hasClass('fa-angle-double-right')) { - $allGutterToggleIcons.removeClass('fa-angle-double-right').addClass('fa-angle-double-left'); - $('aside.right-sidebar').removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed'); - $('.page-with-sidebar').removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed'); - } else { - $allGutterToggleIcons.removeClass('fa-angle-double-left').addClass('fa-angle-double-right'); - $('aside.right-sidebar').removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded'); - $('.page-with-sidebar').removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded'); - } - if (!triggered) { - return Cookies.set("collapsed_gutter", $('.right-sidebar').hasClass('right-sidebar-collapsed')); - } - }); + $document.on('click', '.js-sidebar-toggle', this.sidebarToggleClicked); return $(document).off('click', '.js-issuable-todo').on('click', '.js-issuable-todo', this.toggleTodo); }; + Sidebar.prototype.sidebarToggleClicked = function (e, triggered) { + var $allGutterToggleIcons, $this, $thisIcon; + e.preventDefault(); + $this = $(this); + $thisIcon = $this.find('i'); + $allGutterToggleIcons = $('.js-sidebar-toggle i'); + if ($thisIcon.hasClass('fa-angle-double-right')) { + $allGutterToggleIcons.removeClass('fa-angle-double-right').addClass('fa-angle-double-left'); + $('aside.right-sidebar').removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed'); + $('.page-with-sidebar').removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed'); + } else { + $allGutterToggleIcons.removeClass('fa-angle-double-left').addClass('fa-angle-double-right'); + $('aside.right-sidebar').removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded'); + $('.page-with-sidebar').removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded'); + + if (gl.lazyLoader) gl.lazyLoader.loadCheck(); + } + if (!triggered) { + Cookies.set("collapsed_gutter", $('.right-sidebar').hasClass('right-sidebar-collapsed')); + } + }; + Sidebar.prototype.toggleTodo = function(e) { var $btnText, $this, $todoLoading, ajaxType, url; $this = $(e.currentTarget); diff --git a/app/assets/javascripts/search_autocomplete.js b/app/assets/javascripts/search_autocomplete.js index 38c9a71dd20..f15452ec683 100644 --- a/app/assets/javascripts/search_autocomplete.js +++ b/app/assets/javascripts/search_autocomplete.js @@ -287,6 +287,7 @@ import { isInGroupsPage, isInProjectPage, getGroupSlug, getProjectSlug } from '. onClearInputClick(e) { e.preventDefault(); + this.wrap.toggleClass('has-value', !!e.target.value); return this.searchInput.val('').focus(); } diff --git a/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js b/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js index 1c15a1b877a..3c9de02407e 100644 --- a/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js +++ b/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js @@ -38,7 +38,7 @@ class SidebarMoveIssue { data: (searchTerm, callback) => { this.mediator.fetchAutocompleteProjects(searchTerm) .then(callback) - .catch(() => new Flash('An error occured while fetching projects autocomplete.')); + .catch(() => new Flash('An error occurred while fetching projects autocomplete.')); }, renderRow: project => ` <li> @@ -73,7 +73,7 @@ class SidebarMoveIssue { this.mediator.moveIssue() .catch(() => { - Flash('An error occured while moving the issue.'); + Flash('An error occurred while moving the issue.'); this.$confirmButton .enable() .removeClass('is-loading'); diff --git a/app/assets/javascripts/sidebar/sidebar_mediator.js b/app/assets/javascripts/sidebar/sidebar_mediator.js index e38a8db4cc5..2fe6e5b31f0 100644 --- a/app/assets/javascripts/sidebar/sidebar_mediator.js +++ b/app/assets/javascripts/sidebar/sidebar_mediator.js @@ -41,7 +41,7 @@ export default class SidebarMediator { this.store.setAssigneeData(data); this.store.setTimeTrackingData(data); }) - .catch(() => new Flash('Error occured when fetching sidebar data')); + .catch(() => new Flash('Error occurred when fetching sidebar data')); } fetchAutocompleteProjects(searchTerm) { diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.js index 703f3a56a34..4998a47b691 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.js @@ -27,7 +27,7 @@ export default { <button v-if="showDisabledButton" type="button" - class="btn btn-success btn-sm" + class="js-disabled-merge-button btn btn-success btn-sm" disabled="true"> Merge </button> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.js index aaf9d3304a4..09561694939 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.js @@ -7,7 +7,7 @@ export default { }, template: ` <div class="mr-widget-body media"> - <status-icon status="loading" showDisabledButton /> + <status-icon status="loading" :show-disabled-button="true" /> <div class="media-body space-children"> <span class="bold"> Checking ability to merge automatically diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.js index 4078aad7f83..b25cc3443ef 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.js @@ -16,9 +16,9 @@ export default { <div class="media-body"> <mr-widget-author-and-time actionText="Closed by" - :author="mr.closedBy" - :dateTitle="mr.updatedAt" - :dateReadable="mr.closedAt" + :author="mr.closedEvent.author" + :dateTitle="mr.closedEvent.updatedAt" + :dateReadable="mr.closedEvent.formattedUpdatedAt" /> <section class="mr-info-list"> <p> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.js index f9cb79a0bc1..5d468a085cb 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.js @@ -10,27 +10,37 @@ export default { }, template: ` <div class="mr-widget-body media"> - <status-icon status="failed" showDisabledButton /> + <status-icon + status="failed" + :show-disabled-button="true" /> <div class="media-body space-children"> - <span class="bold"> - There are merge conflicts<span v-if="!mr.canMerge">.</span> - <span v-if="!mr.canMerge"> - Resolve these conflicts or ask someone with write access to this repository to merge it locally - </span> + <span + v-if="mr.shouldBeRebased" + class="bold"> + Fast-forward merge is not possible. + To merge this request, first rebase locally. </span> - <a - v-if="mr.canMerge && mr.conflictResolutionPath" - :href="mr.conflictResolutionPath" - class="btn btn-default btn-xs js-resolve-conflicts-button"> - Resolve conflicts - </a> - <a - v-if="mr.canMerge" - class="btn btn-default btn-xs js-merge-locally-button" - data-toggle="modal" - href="#modal_merge_info"> - Merge locally - </a> + <template v-else> + <span class="bold"> + There are merge conflicts<span v-if="!mr.canMerge">.</span> + <span v-if="!mr.canMerge"> + Resolve these conflicts or ask someone with write access to this repository to merge it locally + </span> + </span> + <a + v-if="mr.canMerge && mr.conflictResolutionPath" + :href="mr.conflictResolutionPath" + class="js-resolve-conflicts-button btn btn-default btn-xs"> + Resolve conflicts + </a> + <a + v-if="mr.canMerge" + class="js-merge-locally-button btn btn-default btn-xs" + data-toggle="modal" + href="#modal_merge_info"> + Merge locally + </a> + </template> </div> </div> `, diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.js index 1cb24549d53..c25d6c359bb 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.js @@ -51,7 +51,7 @@ export default { </span> </template> <template v-else> - <status-icon status="failed" showDisabledButton /> + <status-icon status="failed" :show-disabled-button="true" /> <div class="media-body space-children"> <span class="bold"> <span diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.js index e452260a4d0..74fc52796a0 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.js @@ -69,9 +69,9 @@ export default { <div class="space-children"> <mr-widget-author-and-time actionText="Merged by" - :author="mr.mergedBy" - :dateTitle="mr.updatedAt" - :dateReadable="mr.mergedAt" /> + :author="mr.mergedEvent.author" + :date-title="mr.mergedEvent.updatedAt" + :date-readable="mr.mergedEvent.formattedUpdatedAt" /> <a v-if="mr.canRevertInCurrentMR" v-tooltip diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.js index 9f0a359d01a..1bc0b7e0819 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.js @@ -24,7 +24,7 @@ export default { }, template: ` <div class="mr-widget-body media"> - <status-icon status="failed" showDisabledButton /> + <status-icon status="failed" :show-disabled-button="true" /> <div class="media-body space-children"> <span class="bold js-branch-text"> <span class="capitalize"> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_not_allowed.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_not_allowed.js index 797511d4e3a..00047718201 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_not_allowed.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_not_allowed.js @@ -7,7 +7,7 @@ export default { }, template: ` <div class="mr-widget-body media"> - <status-icon status="success" showDisabledButton /> + <status-icon status="success" :show-disabled-button="true" /> <div class="media-body space-children"> <span class="bold"> Ready to be merged automatically. diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.js index 167a0d4613a..1cedf86e811 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.js @@ -7,7 +7,7 @@ export default { }, template: ` <div class="mr-widget-body media"> - <status-icon status="failed" showDisabledButton /> + <status-icon status="failed" :show-disabled-button="true" /> <div class="media-body space-children"> <span class="bold"> Pipeline blocked. The pipeline for this merge request requires a manual action to proceed diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_failed.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_failed.js index c5be9a0530a..6853ba4b9f8 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_failed.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_failed.js @@ -7,7 +7,7 @@ export default { }, template: ` <div class="mr-widget-body media"> - <status-icon status="failed" showDisabledButton /> + <status-icon status="failed" :show-disabled-button="true" /> <div class="media-body space-children"> <span class="bold"> The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js index ad709da51ee..edc1d191bf2 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js @@ -38,24 +38,40 @@ export default { return this.useCommitMessageWithDescription ? withoutDesc : withDesc; }, - mergeButtonClass() { - const defaultClass = 'btn btn-sm btn-success accept-merge-request'; - const failedClass = `${defaultClass} btn-danger`; - const inActionClass = `${defaultClass} btn-info`; + status() { const { pipeline, isPipelineActive, isPipelineFailed, hasCI, ciStatus } = this.mr; if (hasCI && !ciStatus) { - return failedClass; + return 'failed'; } else if (!pipeline) { - return defaultClass; + return 'success'; } else if (isPipelineActive) { - return inActionClass; + return 'pending'; } else if (isPipelineFailed) { + return 'failed'; + } + + return 'success'; + }, + mergeButtonClass() { + const defaultClass = 'btn btn-sm btn-success accept-merge-request'; + const failedClass = `${defaultClass} btn-danger`; + const inActionClass = `${defaultClass} btn-info`; + + if (this.status === 'failed') { return failedClass; + } else if (this.status === 'pending') { + return inActionClass; } return defaultClass; }, + iconClass() { + if (this.status === 'failed' || !this.commitMessage.length || !this.isMergeAllowed() || this.mr.preventMerge) { + return 'failed'; + } + return 'success'; + }, mergeButtonText() { if (this.isMergingImmediately) { return 'Merge in progress'; @@ -156,6 +172,7 @@ export default { eventHub.$emit('FetchActionsContent'); if (window.mergeRequest) { window.mergeRequest.updateStatusText('status-box-open', 'status-box-merged', 'Merged'); + window.mergeRequest.hideCloseButton(); window.mergeRequest.decreaseCounter(); } stopPolling(); @@ -208,7 +225,7 @@ export default { }, template: ` <div class="mr-widget-body media"> - <status-icon status="success" /> + <status-icon :status="iconClass" /> <div class="media-body"> <div class="mr-widget-body-controls media space-children"> <span class="btn-group append-bottom-5"> @@ -284,10 +301,16 @@ export default { :mr="mr" :is-merge-button-disabled="isMergeButtonDisabled" /> + <span + v-if="mr.ffOnlyEnabled" + class="js-fast-forward-message"> + Fast-forward merge without a merge commit + </span> <button + v-else @click="toggleCommitMessageEditor" :disabled="isMergeButtonDisabled" - class="btn btn-default btn-xs" + class="js-modify-commit-message-button btn btn-default btn-xs" type="button"> Modify commit message </button> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_sha_mismatch.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_sha_mismatch.js index 89f38e5bd2a..af19cf6ab87 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_sha_mismatch.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_sha_mismatch.js @@ -7,7 +7,7 @@ export default { }, template: ` <div class="mr-widget-body media"> - <status-icon status="failed" showDisabledButton /> + <status-icon status="failed" :show-disabled-button="true" /> <div class="media-body space-children"> <span class="bold"> The source branch HEAD has recently changed. Please reload the page and review the changes before merging diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_unresolved_discussions.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_unresolved_discussions.js index d762ca6e640..a119ecbbdfe 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_unresolved_discussions.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_unresolved_discussions.js @@ -10,7 +10,7 @@ export default { }, template: ` <div class="mr-widget-body media"> - <status-icon status="failed" showDisabledButton /> + <status-icon status="failed" :show-disabled-button="true" /> <div class="media-body space-children"> <span class="bold"> There are unresolved discussions. Please resolve these discussions diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_wip.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_wip.js index b11a06899cf..54be1fbe675 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_wip.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_wip.js @@ -38,7 +38,7 @@ export default { }, template: ` <div class="mr-widget-body media"> - <status-icon status="failed" :showDisabledButton="Boolean(mr.removeWIPPath)" /> + <status-icon status="failed" :show-disabled-button="Boolean(mr.removeWIPPath)" /> <div class="media-body space-children"> <span class="bold"> This is a Work in Progress diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js index 29464662578..e554082149b 100644 --- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js +++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js @@ -37,10 +37,8 @@ export default class MergeRequestStore { } this.updatedAt = data.updated_at; - this.mergedAt = MergeRequestStore.getEventDate(data.merge_event); - this.closedAt = MergeRequestStore.getEventDate(data.closed_event); - this.mergedBy = MergeRequestStore.getAuthorObject(data.merge_event); - this.closedBy = MergeRequestStore.getAuthorObject(data.closed_event); + this.mergedEvent = MergeRequestStore.getEventObject(data.merge_event); + this.closedEvent = MergeRequestStore.getEventObject(data.closed_event); this.setToMWPSBy = MergeRequestStore.getAuthorObject({ author: data.merge_user || {} }); this.mergeUserId = data.merge_user_id; this.currentUserId = gon.current_user_id; @@ -57,6 +55,8 @@ export default class MergeRequestStore { this.onlyAllowMergeIfPipelineSucceeds = data.only_allow_merge_if_pipeline_succeeds || false; this.mergeWhenPipelineSucceeds = data.merge_when_pipeline_succeeds || false; this.mergePath = data.merge_path; + this.ffOnlyEnabled = data.ff_only_enabled; + this.shouldBeRebased = !!data.should_be_rebased; this.statusPath = data.status_path; this.emailPatchesPath = data.email_patches_path; this.plainDiffPath = data.plain_diff_path; @@ -118,6 +118,14 @@ export default class MergeRequestStore { } } + static getEventObject(event) { + return { + author: MergeRequestStore.getAuthorObject(event), + updatedAt: gl.utils.formatDate(MergeRequestStore.getEventUpdatedAtDate(event)), + formattedUpdatedAt: MergeRequestStore.getEventDate(event), + }; + } + static getAuthorObject(event) { if (!event) { return {}; @@ -131,6 +139,14 @@ export default class MergeRequestStore { }; } + static getEventUpdatedAtDate(event) { + if (!event) { + return ''; + } + + return event.updated_at; + } + static getEventDate(event) { const timeagoInstance = new Timeago(); @@ -138,7 +154,7 @@ export default class MergeRequestStore { return ''; } - return timeagoInstance.format(event.updated_at); + return timeagoInstance.format(MergeRequestStore.getEventUpdatedAtDate(event)); } } diff --git a/app/assets/javascripts/vue_shared/components/clipboard_button.vue b/app/assets/javascripts/vue_shared/components/clipboard_button.vue new file mode 100644 index 00000000000..3a7143c450e --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/clipboard_button.vue @@ -0,0 +1,32 @@ +<script> + /** + * Falls back to the code used in `copy_to_clipboard.js` + */ + + export default { + name: 'clipboardButton', + props: { + text: { + type: String, + required: true, + }, + title: { + type: String, + required: true, + }, + }, + }; +</script> + +<template> + <button + type="button" + class="btn btn-transparent btn-clipboard" + :data-title="title" + :data-clipboard-text="text"> + <i + aria-hidden="true" + class="fa fa-clipboard"> + </i> + </button> +</template> diff --git a/app/assets/javascripts/vue_shared/translate.js b/app/assets/javascripts/vue_shared/translate.js index f83c4b00761..2c7886ec308 100644 --- a/app/assets/javascripts/vue_shared/translate.js +++ b/app/assets/javascripts/vue_shared/translate.js @@ -2,6 +2,7 @@ import { __, n__, s__, + sprintf, } from '../locale'; export default (Vue) => { @@ -37,6 +38,7 @@ export default (Vue) => { @returns {String} Translated context based text **/ s__, + sprintf, }, }); }; diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss index 923d14f2c3d..74b846217bb 100644 --- a/app/assets/stylesheets/framework.scss +++ b/app/assets/stylesheets/framework.scss @@ -31,10 +31,12 @@ @import "framework/mobile"; @import "framework/modal"; @import "framework/nav"; +@import "framework/new-nav"; @import "framework/pagination"; @import "framework/panels"; @import "framework/selects"; @import "framework/sidebar"; +@import "framework/new-sidebar"; @import "framework/tables"; @import "framework/notes"; @import "framework/timeline"; diff --git a/app/assets/stylesheets/framework/avatar.scss b/app/assets/stylesheets/framework/avatar.scss index bdcbd4021b3..f1aedc227f3 100644 --- a/app/assets/stylesheets/framework/avatar.scss +++ b/app/assets/stylesheets/framework/avatar.scss @@ -23,6 +23,7 @@ &.s60 { @include avatar-size(60px, 12px); } &.s70 { @include avatar-size(70px, 14px); } &.s90 { @include avatar-size(90px, 15px); } + &.s100 { @include avatar-size(100px, 15px); } &.s110 { @include avatar-size(110px, 15px); } &.s140 { @include avatar-size(140px, 15px); } &.s160 { @include avatar-size(160px, 20px); } @@ -78,6 +79,7 @@ &.s60 { font-size: 32px; line-height: 58px; } &.s70 { font-size: 34px; line-height: 70px; } &.s90 { font-size: 36px; line-height: 88px; } + &.s100 { font-size: 36px; line-height: 98px; } &.s110 { font-size: 40px; line-height: 108px; font-weight: $gl-font-weight-normal; } &.s140 { font-size: 72px; line-height: 138px; } &.s160 { font-size: 96px; line-height: 158px; } diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss index 5c68059f485..1d72a70f0f5 100644 --- a/app/assets/stylesheets/framework/blocks.scss +++ b/app/assets/stylesheets/framework/blocks.scss @@ -260,7 +260,7 @@ position: relative; border: 1px solid $blue-300; border-radius: $border-radius-default; - background-color: $blue-25; + background-color: $blue-50; justify-content: center; .dismiss-button { diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index 706a9cffe87..96f9dda26c4 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -11,6 +11,7 @@ .prepend-top-10 { margin-top: 10px; } .prepend-top-default { margin-top: $gl-padding !important; } .prepend-top-20 { margin-top: 20px; } +.prepend-left-4 { margin-left: 4px; } .prepend-left-5 { margin-left: 5px; } .prepend-left-10 { margin-left: 10px; } .prepend-left-default { margin-left: $gl-padding; } @@ -129,11 +130,6 @@ span.update-author { } } -.user-mention { - color: $user-mention-color; - font-weight: $gl-font-weight-bold; -} - .field_with_errors { display: inline; } diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index 2bcd23a15e6..fa92d4ccf4f 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -745,6 +745,10 @@ #{$selector}.dropdown-menu-nav { margin-bottom: 24px; + &.dropdown-open-top { + margin-bottom: $dropdown-vertical-offset; + } + li { display: block; padding: 0 1px; @@ -779,6 +783,14 @@ white-space: normal; width: 100%; + &.dropdown-menu-user-link { + white-space: nowrap; + + .dropdown-menu-user-username { + display: block; + } + } + // make sure the text color is not overriden &.text-danger { color: $brand-danger; @@ -865,6 +877,13 @@ min-width: 100%; } } + + header.navbar-gitlab-new .header-content .dropdown { + .dropdown-menu { + left: 0; + min-width: 100%; + } + } } @include new-style-dropdown('.breadcrumbs-list .dropdown '); diff --git a/app/assets/stylesheets/framework/gfm.scss b/app/assets/stylesheets/framework/gfm.scss index dbdd5a4464b..34a35734acc 100644 --- a/app/assets/stylesheets/framework/gfm.scss +++ b/app/assets/stylesheets/framework/gfm.scss @@ -6,3 +6,14 @@ .gfm-commit_range { @extend .commit-sha; } + +.gfm-project_member { + padding: 0 2px; + border-radius: #{$border-radius-default / 2}; + background-color: $user-mention-bg; + + &:hover { + background-color: $user-mention-bg-hover; + text-decoration: none; + } +} diff --git a/app/assets/stylesheets/framework/gitlab-theme.scss b/app/assets/stylesheets/framework/gitlab-theme.scss index f844d6f1d5a..6b69e8018be 100644 --- a/app/assets/stylesheets/framework/gitlab-theme.scss +++ b/app/assets/stylesheets/framework/gitlab-theme.scss @@ -6,7 +6,7 @@ // Header header.navbar-gitlab-new { - background: linear-gradient(to right, $color-900, $color-800); + background-color: $color-900; .navbar-collapse { color: $color-200; @@ -126,7 +126,7 @@ .search-input-wrap { .search-icon, .clear-icon { - color: rgba($color-200, .8); + fill: rgba($color-200, .8); } } @@ -141,7 +141,7 @@ .search-input-wrap { .search-icon { - color: rgba($color-200, .8); + fill: rgba($color-200, .8); } } } @@ -201,7 +201,7 @@ body { @include gitlab-theme($theme-gray-900, $theme-gray-700, $theme-gray-800, $theme-gray-700, $theme-gray-700, $theme-gray-100, $theme-gray-700); header.navbar-gitlab-new { - background: $theme-gray-100; + background-color: $theme-gray-100; box-shadow: 0 2px 0 0 $border-color; .logo-text svg { @@ -242,17 +242,21 @@ body { &:hover { background-color: $white-light; - box-shadow: inset 0 0 0 1px $blue-100; + box-shadow: inset 0 0 0 1px $blue-200; .location-badge { - box-shadow: inset 0 0 0 1px $blue-100; + box-shadow: inset 0 0 0 1px $blue-200; } } } .search-input-wrap { .search-icon { - color: $theme-gray-200; + fill: $theme-gray-200; + } + + .search-input { + color: $gl-text-color; } } diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index ab3c34df1fb..d932ea8794f 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -109,8 +109,7 @@ header { .user-counter { svg { - height: 16px; - width: 23px; + margin-right: 3px; } } @@ -133,16 +132,16 @@ header { } &.navbar-gitlab-new { - .fa-times { + .close-icon { display: none; } .menu-expanded { - .fa-ellipsis-v { + .more-icon { display: none; } - .fa-times { + .close-icon { display: block; } } diff --git a/app/assets/stylesheets/framework/images.scss b/app/assets/stylesheets/framework/images.scss index 60d61c68d63..59bfc5a8d77 100644 --- a/app/assets/stylesheets/framework/images.scss +++ b/app/assets/stylesheets/framework/images.scss @@ -27,7 +27,9 @@ } svg { + &.s8 { @include svg-size(8px); } &.s16 { @include svg-size(16px); } + &.s18 { @include svg-size(18px); } &.s24 { @include svg-size(24px); } &.s32 { @include svg-size(32px); } &.s48 { @include svg-size(48px); } diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index 0fb19344510..badc7b0eba3 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -229,6 +229,10 @@ ul.content-list { .label-default { color: $gl-text-color-secondary; } + + .avatar-cell { + align-self: flex-start; + } } .panel > .content-list > li { diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss index d40b65bb2cc..2fee2164190 100644 --- a/app/assets/stylesheets/framework/mixins.scss +++ b/app/assets/stylesheets/framework/mixins.scss @@ -142,5 +142,41 @@ } @mixin green-status-color { - @include status-color($green-50, $green-500, $green-700); + @include status-color($green-100, $green-500, $green-700); +} + +@mixin fade($gradient-direction, $gradient-color) { + visibility: hidden; + opacity: 0; + z-index: 2; + position: absolute; + bottom: 12px; + width: 43px; + height: 30px; + transition-duration: .3s; + -webkit-transform: translateZ(0); + background: linear-gradient(to $gradient-direction, $gradient-color 45%, rgba($gradient-color, 0.4)); + + &.scrolling { + visibility: visible; + opacity: 1; + transition-duration: .3s; + } + + .fa { + position: relative; + top: 5px; + font-size: 18px; + } +} + +@mixin scrolling-links() { + overflow-x: auto; + overflow-y: hidden; + -webkit-overflow-scrolling: touch; + display: flex; + + &::-webkit-scrollbar { + display: none; + } } diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 2f7717760ec..f8777d1fd9d 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -1,38 +1,4 @@ -@mixin fade($gradient-direction, $gradient-color) { - visibility: hidden; - opacity: 0; - z-index: 2; - position: absolute; - bottom: 12px; - width: 43px; - height: 30px; - transition-duration: .3s; - -webkit-transform: translateZ(0); - background: linear-gradient(to $gradient-direction, $gradient-color 45%, rgba($gradient-color, 0.4)); - - &.scrolling { - visibility: visible; - opacity: 1; - transition-duration: .3s; - } - - .fa { - position: relative; - top: 5px; - font-size: 18px; - } -} -@mixin scrolling-links() { - overflow-x: auto; - overflow-y: hidden; - -webkit-overflow-scrolling: touch; - display: flex; - - &::-webkit-scrollbar { - display: none; - } -} .nav-links { display: flex; diff --git a/app/assets/stylesheets/new_nav.scss b/app/assets/stylesheets/framework/new-nav.scss index 8c5bafac637..7899be2c2d3 100644 --- a/app/assets/stylesheets/new_nav.scss +++ b/app/assets/stylesheets/framework/new-nav.scss @@ -120,17 +120,24 @@ header.navbar-gitlab-new { .container-fluid { .navbar-toggle { min-width: 45px; - padding: 4px $gl-padding; + padding: 0 $gl-padding; margin-right: -7px; - font-size: 14px; text-align: center; color: currentColor; + svg { + fill: currentColor; + } + &:hover, &:focus, &.active { color: currentColor; background-color: transparent; + + svg { + fill: currentColor; + } } } @@ -279,10 +286,6 @@ header.navbar-gitlab-new { } } -.admin-icon i { - font-size: 18px; -} - .caret-down { height: 11px; width: 11px; @@ -292,76 +295,7 @@ header.navbar-gitlab-new { .header-user .dropdown-menu-nav, .header-new .dropdown-menu-nav { - margin-top: 4px; -} - -.search { - margin: 4px 8px 0; - - form { - height: 32px; - border: 0; - border-radius: $border-radius-default; - transition: border-color ease-in-out 0.15s, background-color ease-in-out 0.15s; - - &:hover { - box-shadow: none; - } - } - - &.search-active form { - box-shadow: none; - - .search-input { - color: $gl-text-color; - transition: color ease-in-out 0.15s; - } - - .search-input::placeholder { - color: $gl-text-color-tertiary; - } - - .search-input-wrap { - .search-icon, - .clear-icon { - color: $gl-text-color-tertiary; - transition: color ease-in-out 0.15s; - } - } - } - - .search-input { - color: $white-light; - background: none; - transition: color ease-in-out 0.15s; - } - - .search-input::placeholder { - transition: color ease-in-out 0.15s; - } - - .location-badge { - font-size: 12px; - margin: -4px 4px -4px -4px; - line-height: 25px; - padding: 4px 8px; - border-radius: 2px 0 0 2px; - height: 32px; - transition: border-color ease-in-out 0.15s; - } - - &.search-active { - .location-badge { - background-color: $nav-badge-bg; - border-color: $border-color; - } - - .search-input-wrap { - .clear-icon { - color: $white-light; - } - } - } + margin-top: $dropdown-vertical-offset; } .breadcrumbs { @@ -375,6 +309,8 @@ header.navbar-gitlab-new { display: flex; width: 100%; position: relative; + padding-top: $gl-padding / 2; + padding-bottom: $gl-padding / 2; align-items: center; border-bottom: 1px solid $border-color; } @@ -386,11 +322,6 @@ header.navbar-gitlab-new { align-self: center; color: $gl-text-color-secondary; - @media (max-width: $screen-xs-max) { - padding-left: 17px; - border-left: 1px solid $gl-text-color-quaternary; - } - .avatar-tile { margin-right: 4px; border: 1px solid $border-color; @@ -420,6 +351,7 @@ header.navbar-gitlab-new { display: flex; align-items: center; position: relative; + padding: 2px 0; &:not(:last-child) { margin-right: 20px; @@ -455,7 +387,7 @@ header.navbar-gitlab-new { margin: 0; font-size: 12px; font-weight: 600; - line-height: 1; + line-height: 16px; a { color: $gl-text-color; diff --git a/app/assets/stylesheets/new_sidebar.scss b/app/assets/stylesheets/framework/new-sidebar.scss index 9c404b7e542..8332cec2962 100644 --- a/app/assets/stylesheets/new_sidebar.scss +++ b/app/assets/stylesheets/framework/new-sidebar.scss @@ -56,8 +56,8 @@ $new-sidebar-collapsed-width: 50px; color: $hover-color; .settings-avatar { - i { - color: $hover-color; + svg { + fill: $hover-color; } } } @@ -76,12 +76,9 @@ $new-sidebar-collapsed-width: 50px; .settings-avatar { background-color: $white-light; - i { - font-size: 20px; - width: 100%; - color: $gl-text-color-secondary; - text-align: center; - align-self: center; + svg { + fill: $gl-text-color-secondary; + margin: auto; } } @@ -177,16 +174,16 @@ $new-sidebar-collapsed-width: 50px; .nav-icon-container { display: flex; margin-right: 8px; - - svg { - height: 16px; - width: 16px; - } } .fly-out-top-item { display: none; } + + svg { + height: 16px; + width: 16px; + } } .nav-sidebar-inner-scroll { @@ -354,18 +351,22 @@ $new-sidebar-collapsed-width: 50px; display: flex; align-items: center; - i { - font-size: 20px; + svg { + fill: $gl-text-color-secondary; margin-right: 8px; } - .fa-angle-double-right { + .icon-angle-double-right { display: none; } &:hover { background-color: $border-color; color: $gl-text-color; + + svg { + fill: $gl-text-color; + } } } @@ -407,15 +408,16 @@ $new-sidebar-collapsed-width: 50px; .toggle-sidebar-button { width: $new-sidebar-collapsed-width - 2px; - padding: 16px 18px; + padding: 16px; .collapse-text, - .fa-angle-double-left { + .icon-angle-double-left { display: none; } - .fa-angle-double-right { + .icon-angle-double-right { display: block; + margin: 0; } } } @@ -461,6 +463,13 @@ $new-sidebar-collapsed-width: 50px; font-size: 18px; } } + + @media (max-width: $screen-xs-max) { + + .breadcrumbs-links { + padding-left: 17px; + border-left: 1px solid $gl-text-color-quaternary; + } + } } @media (max-width: $screen-xs-max) { diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss index 6c14e8b97e0..50f1445bc2e 100644 --- a/app/assets/stylesheets/framework/selects.scss +++ b/app/assets/stylesheets/framework/selects.scss @@ -48,31 +48,24 @@ } &:hover { - background-color: $white-normal; - border-color: $border-white-normal; + border-color: $gray-darkest; color: $gl-text-color; } } } -.select2-drop { - box-shadow: $select2-drop-shadow1 0 0 1px 0, $select2-drop-shadow2 0 2px 18px 0; - border-radius: $border-radius-default; - border: none; +.select2-drop, +.select2-drop.select2-drop-above { + box-shadow: 0 2px 4px $dropdown-shadow-color; + border-radius: $border-radius-base; + border: 1px solid $dropdown-border-color; min-width: 175px; + color: $gl-text-color; } -.select2-results .select2-result-label, -.select2-more-results { - padding: 10px 15px; -} - -.select2-drop { - color: $gl-grayish-blue; -} - -.select2-highlighted { - background: $gl-link-color !important; +.select2-drop.select2-drop-above.select2-drop-active { + border-top: 1px solid $dropdown-border-color; + margin-top: -6px; } .select2-results li.select2-result-with-children > .select2-result-label { @@ -87,13 +80,11 @@ } } -.select2-dropdown-open { +.select2-dropdown-open, +.select2-dropdown-open.select2-drop-above { .select2-choice { - border-color: $border-white-normal; + border-color: $gray-darkest; outline: 0; - background-image: none; - background-color: $white-dark; - box-shadow: $gl-btn-active-gradient; } } @@ -131,28 +122,14 @@ } } } - - &.select2-container-active .select2-choices, - &.select2-dropdown-open .select2-choices { - border-color: $border-white-normal; - box-shadow: $gl-btn-active-gradient; - } } .select2-drop-active { - margin-top: 6px; + margin-top: $dropdown-vertical-offset; font-size: 14px; - &.select2-drop-above { - margin-bottom: 8px; - } - .select2-results { max-height: 350px; - - .select2-highlighted { - background: $gl-primary; - } } } @@ -186,19 +163,35 @@ background-size: 16px 16px !important; } -.select2-results .select2-no-results, -.select2-results .select2-searching, -.select2-results .select2-ajax-error, -.select2-results .select2-selection-limit { - background: $gray-light; - display: list-item; - padding: 10px 15px; -} - - .select2-results { margin: 0; - padding: 10px 0; + padding: #{$gl-padding / 2} 0; + + .select2-no-results, + .select2-searching, + .select2-ajax-error, + .select2-selection-limit { + background: transparent; + padding: #{$gl-padding / 2} $gl-padding; + } + + .select2-result-label, + .select2-more-results { + padding: #{$gl-padding / 2} $gl-padding; + } + + .select2-highlighted { + background: transparent; + color: $gl-text-color; + + .select2-result-label { + background: $dropdown-item-hover-bg; + } + } + + .select2-result { + padding: 0 1px; + } } .ajax-users-select { @@ -265,56 +258,10 @@ min-width: 250px !important; } -// TODO: change global style -.ajax-project-dropdown, -.ajax-users-dropdown, -body[data-page="projects:edit"] #select2-drop, -body[data-page="projects:new"] #select2-drop, -body[data-page="projects:merge_requests:edit"] #select2-drop, -body[data-page="projects:blob:new"] #select2-drop, -body[data-page="profiles:show"] #select2-drop, -body[data-page="admin:groups:show"] #select2-drop, -body[data-page="projects:issues:show"] #select2-drop, -body[data-page="projects:blob:edit"] #select2-drop { - &.select2-drop { - border: 1px solid $dropdown-border-color; - border-radius: $border-radius-base; - color: $gl-text-color; - } - - &.select2-drop-above { - border-top: none; - margin-top: -4px; - } - - .select2-results { - .select2-no-results, - .select2-searching, - .select2-ajax-error, - .select2-selection-limit { - background: transparent; - } - - .select2-result { - padding: 0 1px; - - .select2-match { - font-weight: $gl-font-weight-bold; - text-decoration: none; - } - - .select2-result-label { - padding: #{$gl-padding / 2} $gl-padding; - } - - &.select2-highlighted { - background-color: transparent !important; - color: $gl-text-color; - - .select2-result-label { - background-color: $dropdown-item-hover-bg; - } - } - } +.select2-result-selectable, +.select2-result-unselectable { + .select2-match { + font-weight: $gl-font-weight-bold; + text-decoration: none; } } diff --git a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss index 4c35e3a9c3c..3ea77eb7a43 100644 --- a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss +++ b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss @@ -137,7 +137,7 @@ $well-border: #eee; //## $code-color: $red-600; -$code-bg: lighten($red-50, 2%); +$code-bg: lighten($red-100, 2%); $kbd-color: $white-light; $kbd-bg: #333; diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index a3da9fd44e8..60260355765 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -6,6 +6,8 @@ $gutter_width: 290px; $gutter_inner_width: 250px; $sidebar-transition-duration: .15s; $sidebar-breakpoint: 1024px; +$default-transition-duration: .15s; +$right-sidebar-transition-duration: .3s; /* * Color schema @@ -27,46 +29,45 @@ $gray-dark: darken($gray-light, $darken-dark-factor); $gray-darker: #eee; $gray-darkest: #c4c4c4; -$green-25: #f6fcf8; -$green-50: #e4f5eb; -$green-100: #bae6cc; -$green-200: #8dd5aa; -$green-300: #5fc488; -$green-400: #3cb76f; +$green-50: #f1fdf6; +$green-100: #dcf5e7; +$green-200: #b3e6c8; +$green-300: #75d09b; +$green-400: #37b96d; $green-500: #1aaa55; $green-600: #168f48; $green-700: #12753a; $green-800: #0e5a2d; $green-900: #0a4020; +$green-950: #072b15; -$blue-25: #f6fafd; -$blue-50: #e4eff9; -$blue-100: #bcd7f1; -$blue-200: #8fbce8; -$blue-300: #62a1df; -$blue-400: #418cd8; +$blue-50: #f6fafe; +$blue-100: #e4f0fb; +$blue-200: #b8d6f4; +$blue-300: #73afea; +$blue-400: #2e87e0; $blue-500: #1f78d1; $blue-600: #1b69b6; $blue-700: #17599c; $blue-800: #134a81; $blue-900: #0f3b66; +$blue-950: #0a2744; -$orange-25: #fffcf8; -$orange-50: #fff2e1; -$orange-100: #fedfb3; -$orange-200: #feca81; -$orange-300: #fdb44f; -$orange-400: #fca429; +$orange-50: #fffaf4; +$orange-100: #fff1de; +$orange-200: #fed69f; +$orange-300: #fdbc60; +$orange-400: #fca121; $orange-500: #fc9403; $orange-600: #de7e00; $orange-700: #c26700; -$orange-800: #a35100; -$orange-900: #853b00; +$orange-800: #a35200; +$orange-900: #853c00; +$orange-950: #592800; -$red-25: #fef7f6; -$red-50: #fbe7e4; -$red-100: #f4c4bc; -$red-200: #ed9d90; +$red-50: #fef6f5; +$red-100: #fbe5e1; +$red-200: #f2b4a9; $red-300: #e67664; $red-400: #e05842; $red-500: #db3b21; @@ -74,6 +75,7 @@ $red-600: #c0341d; $red-700: #a62d19; $red-800: #8b2615; $red-900: #711e11; +$red-950: #4b140b; // GitLab themes @@ -184,8 +186,8 @@ $list-text-disabled-color: $gl-text-color-tertiary; $list-border-light: #eee; $list-border: rgba(0, 0, 0, 0.05); $list-text-height: 42px; -$list-warning-row-bg: $orange-50; -$list-warning-row-border: $orange-100; +$list-warning-row-bg: $orange-100; +$list-warning-row-border: $orange-200; $list-warning-row-color: $orange-700; /* @@ -214,8 +216,8 @@ $gl-sidebar-padding: 22px; /* * Misc */ -$row-hover: $blue-25; -$row-hover-border: $blue-100; +$row-hover: $blue-50; +$row-hover-border: $blue-200; $progress-color: #c0392b; $header-height: 50px; $new-navbar-height: 40px; @@ -260,13 +262,14 @@ $well-pre-bg: #eee; $well-pre-color: #555; $loading-color: #555; $update-author-color: #999; -$user-mention-color: #2fa0bb; +$user-mention-bg: rgba($blue-500, 0.044); +$user-mention-bg-hover: rgba($blue-500, 0.15); $time-color: #999; $project-member-show-color: #aaa; $gl-promo-color: #aaa; $error-bg: $red-400; -$warning-message-bg: $orange-50; -$warning-message-border: $orange-100; +$warning-message-bg: $orange-100; +$warning-message-border: $orange-200; $warning-message-color: $orange-700; $control-group-descr-color: #666; $table-permission-x-bg: #d9edf7; @@ -325,6 +328,7 @@ $regular_font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-San * Dropdowns */ $dropdown-width: 300px; +$dropdown-vertical-offset: 4px; $dropdown-link-color: #555; $dropdown-link-hover-bg: $row-hover; $dropdown-empty-row-bg: rgba(#000, .04); @@ -451,17 +455,17 @@ $builds-trace-bg: #111; /* * Callout */ -$callout-danger-bg: $red-50; -$callout-danger-border: $red-100; +$callout-danger-bg: $red-100; +$callout-danger-border: $red-200; $callout-danger-color: $red-700; -$callout-warning-bg: $orange-50; -$callout-warning-border: $orange-100; +$callout-warning-bg: $orange-100; +$callout-warning-border: $orange-200; $callout-warning-color: $orange-700; -$callout-info-bg: $blue-50; -$callout-info-border: $blue-100; +$callout-info-bg: $blue-100; +$callout-info-border: $blue-200; $callout-info-color: $blue-700; -$callout-success-bg: $green-50; -$callout-success-border: $green-100; +$callout-success-bg: $green-100; +$callout-success-border: $green-200; $callout-success-color: $green-700; /* diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss index 700be173039..3305a482a0d 100644 --- a/app/assets/stylesheets/pages/boards.scss +++ b/app/assets/stylesheets/pages/boards.scss @@ -55,6 +55,15 @@ .boards-app { position: relative; + + @media (min-width: $screen-sm-min) { + transition: width $right-sidebar-transition-duration; + width: 100%; + + &.is-compact { + width: calc(100% - #{$gutter_width}); + } + } } .boards-app-loading { @@ -78,11 +87,6 @@ height: calc(100vh - 222px); // scss-lint:enable DuplicateProperty min-height: 475px; - transition: width .2s; - - &.is-compact { - width: calc(100% - 290px); - } } } @@ -412,14 +416,6 @@ .page-with-layout-nav.page-with-sub-nav .issue-boards-sidebar, .page-with-new-sidebar.page-with-sidebar .issue-boards-sidebar { - position: absolute; - - &.right-sidebar { - top: 0; - bottom: 0; - height: 100%; - } - .issuable-sidebar-header { position: relative; } @@ -457,8 +453,8 @@ .right-sidebar.right-sidebar-expanded { &.boards-sidebar-slide-enter-active, &.boards-sidebar-slide-leave-active { - transition: width .2s, - padding .2s; + transition: width $right-sidebar-transition-duration, + padding $right-sidebar-transition-duration; } &.boards-sidebar-slide-enter, diff --git a/app/assets/stylesheets/pages/container_registry.scss b/app/assets/stylesheets/pages/container_registry.scss index 3266714396e..dfff3e15556 100644 --- a/app/assets/stylesheets/pages/container_registry.scss +++ b/app/assets/stylesheets/pages/container_registry.scss @@ -9,6 +9,14 @@ .container-image-head { padding: 0 16px; line-height: 4em; + + .btn-link { + padding: 0; + + &:focus { + outline: none; + } + } } .table.tags { diff --git a/app/assets/stylesheets/pages/convdev_index.scss b/app/assets/stylesheets/pages/convdev_index.scss index 16702442f50..fb1899284fd 100644 --- a/app/assets/stylesheets/pages/convdev_index.scss +++ b/app/assets/stylesheets/pages/convdev_index.scss @@ -83,7 +83,7 @@ $space-between-cards: 8px; border-top-color: $color-low-score; .card-score-big { - background-color: $red-25; + background-color: $red-50; } } @@ -91,7 +91,7 @@ $space-between-cards: 8px; border-top-color: $color-average-score; .card-score-big { - background-color: $orange-25; + background-color: $orange-50; } } @@ -99,7 +99,7 @@ $space-between-cards: 8px; border-top-color: $color-high-score; .card-score-big { - background-color: $green-25; + background-color: $green-50; } } diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index 951580ea1fe..fb23343b966 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -77,6 +77,18 @@ word-wrap: break-word; } } + + &.left-side-selected { + td.line_content.parallel.right-side { + @include user-select(none); + } + } + + &.right-side-selected { + td.line_content.parallel.left-side { + @include user-select(none); + } + } } tr.line_holder.parallel { @@ -451,7 +463,7 @@ } .files { - margin-top: -1px; + margin-top: 1px; .diff-file:last-child { margin-bottom: 0; @@ -535,7 +547,6 @@ } .diff-notes-collapse { - position: relative; width: 19px; height: 19px; padding: 0; @@ -543,11 +554,7 @@ z-index: 100; svg { - position: absolute; - left: 50%; - top: 50%; - margin-left: -5.5px; - margin-top: -5.5px; + vertical-align: text-top; } path { @@ -586,11 +593,6 @@ top: 76px; } - + .files, - + .alert { - margin-top: 1px; - } - &:not(.is-stuck) .diff-stats-additions-deletions-collapsed { display: none; } @@ -605,11 +607,6 @@ .inline-parallel-buttons { display: none; } - - + .files, - + .alert { - margin-top: 32px; - } } } } diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss index 9362d80d4e6..6a9c2578d95 100644 --- a/app/assets/stylesheets/pages/environments.scss +++ b/app/assets/stylesheets/pages/environments.scss @@ -207,10 +207,13 @@ } .prometheus-state { - margin-top: 10px; + max-width: 430px; + margin: 10px auto; + text-align: center; - .state-button-section { - margin-top: 10px; + .state-svg { + max-width: 80vw; + margin: 0 auto; } } diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index d01ee4b033c..7eb28354e6d 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -7,7 +7,7 @@ .is-confidential { color: $orange-600; - background-color: $orange-50; + background-color: $orange-100; border-radius: $border-radius-default; padding: 5px; margin: 0 3px 0 -4px; @@ -223,14 +223,14 @@ top: $new-navbar-height; bottom: 0; right: 0; - transition: width .3s; + transition: width $right-sidebar-transition-duration; background: $gray-light; z-index: 200; overflow: hidden; .issuable-sidebar { width: calc(100% + 100px); - height: calc(100% - #{$new-navbar-height}); + height: 100%; overflow-y: scroll; overflow-x: hidden; -webkit-overflow-scrolling: touch; diff --git a/app/assets/stylesheets/pages/merge_conflicts.scss b/app/assets/stylesheets/pages/merge_conflicts.scss index 35cefd449f1..dbf3e2b763c 100644 --- a/app/assets/stylesheets/pages/merge_conflicts.scss +++ b/app/assets/stylesheets/pages/merge_conflicts.scss @@ -255,7 +255,7 @@ $colors: ( &.saved { .editor { - border-top: solid 2px $green-200; + border-top: solid 2px $green-300; } } diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss index 5d7c85b16ef..74d9acb5490 100644 --- a/app/assets/stylesheets/pages/note_form.scss +++ b/app/assets/stylesheets/pages/note_form.scss @@ -103,7 +103,7 @@ .confidential-issue-warning { color: $orange-600; - background-color: $orange-50; + background-color: $orange-100; border-radius: $border-radius-default $border-radius-default 0 0; border: 1px solid $border-gray-normal; border-bottom: none; @@ -362,7 +362,7 @@ .dropdown-menu { top: initial; - bottom: 40px; + bottom: 100%; width: 298px; } diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 9d03a042aa3..086dd528579 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -644,20 +644,20 @@ button.mini-pipeline-graph-dropdown-toggle { // Dropdown button animation in mini pipeline graph &.ci-status-icon-success { - @include mini-pipeline-graph-color($green-50, $green-500, $green-600); + @include mini-pipeline-graph-color($green-100, $green-500, $green-600); } &.ci-status-icon-failed { - @include mini-pipeline-graph-color($red-50, $red-500, $red-600); + @include mini-pipeline-graph-color($red-100, $red-500, $red-600); } &.ci-status-icon-pending, &.ci-status-icon-success_with_warnings { - @include mini-pipeline-graph-color($orange-50, $orange-500, $orange-600); + @include mini-pipeline-graph-color($orange-100, $orange-500, $orange-600); } &.ci-status-icon-running { - @include mini-pipeline-graph-color($blue-50, $blue-400, $blue-600); + @include mini-pipeline-graph-color($blue-100, $blue-400, $blue-600); } &.ci-status-icon-canceled, diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss index 8b1f4b75693..6c521bb06ee 100644 --- a/app/assets/stylesheets/pages/profile.scss +++ b/app/assets/stylesheets/pages/profile.scss @@ -291,7 +291,7 @@ table.u2f-registrations { .bordered-box { border: 1px solid $blue-300; border-radius: $border-radius-default; - background-color: $blue-25; + background-color: $blue-50; position: relative; display: flex; justify-content: center; @@ -379,7 +379,7 @@ table.u2f-registrations { .nav-wip { border: 1px solid $blue-500; - background: $blue-25; + background: $blue-50; padding: $gl-padding; margin-bottom: $gl-padding; diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 6400b72742c..a086c11324d 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -499,64 +499,56 @@ a.deploy-project-label { } } -.fork-namespaces { - .row { - -webkit-flex-wrap: wrap; - display: -webkit-flex; - display: flex; - flex-wrap: wrap; - justify-content: flex-start; +.fork-thumbnail { + height: 200px; + width: calc((100% / 2) - #{$gl-padding * 2}); - .fork-thumbnail { - border-radius: $border-radius-base; - background-color: $white-light; - border: 1px solid $border-white-light; - height: 202px; - margin: $gl-padding; - text-align: center; - width: 169px; + @media (min-width: $screen-md-min) { + width: calc((100% / 4) - #{$gl-padding * 2}); + } - &:hover, - &.forked { - background-color: $row-hover; - border-color: $row-hover-border; - } + @media (min-width: $screen-lg-min) { + width: calc((100% / 5) - #{$gl-padding * 2}); + } - .no-avatar { - width: 100px; - height: 100px; - background-color: $gray-light; - border: 1px solid $white-normal; - margin: 0 auto; - border-radius: 50%; - - i { - font-size: 100px; - color: $white-normal; - } - } + &:hover:not(.disabled), + &.forked { + background-color: $row-hover; + border-color: $row-hover-border; + } - a { - display: block; - width: 100%; - height: 100%; - padding-top: $gl-padding; - color: $gl-text-color; - - .caption { - min-height: 30px; - padding: $gl-padding 0; - } - } + .avatar-container, + .identicon { + float: none; + margin-left: auto; + margin-right: auto; + } - img { - border-radius: 50%; - max-width: 100px; - } + a { + display: block; + width: 100%; + height: 100%; + padding-top: $gl-padding; + text-decoration: none; + + &.disabled { + opacity: .3; + cursor: not-allowed; } } } +.fork-thumbnail-container { + display: flex; + flex-wrap: wrap; + margin-left: -$gl-padding; + margin-right: -$gl-padding; + + > h5 { + width: 100%; + } +} + .project-template, .project-import { .form-group { diff --git a/app/assets/stylesheets/pages/repo.scss b/app/assets/stylesheets/pages/repo.scss index 4d4d92f9494..c36fe25f74d 100644 --- a/app/assets/stylesheets/pages/repo.scss +++ b/app/assets/stylesheets/pages/repo.scss @@ -54,6 +54,10 @@ border-radius: $border-radius-default; color: $almost-black; + .code.white pre .hll { + background-color: $well-light-border !important; + } + .tree-content-holder { display: flex; min-height: 300px; diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss index 13dd7b5a780..89ebe3f9917 100644 --- a/app/assets/stylesheets/pages/search.scss +++ b/app/assets/stylesheets/pages/search.scss @@ -28,9 +28,7 @@ input[type="checkbox"]:hover { } .search { - margin-right: 10px; - margin-left: 10px; - margin-top: ($header-height - 35) / 2; + margin: 4px 8px 0; form { @extend .form-control; @@ -38,15 +36,23 @@ input[type="checkbox"]:hover { padding: 4px; width: $search-input-width; line-height: 24px; + height: 32px; + border: 0; + border-radius: $border-radius-default; + transition: border-color ease-in-out $default-transition-duration, background-color ease-in-out $default-transition-duration; &:hover { - border-color: lighten($dropdown-input-focus-border, 20%); - box-shadow: 0 0 4px lighten($search-input-focus-shadow-color, 20%); + box-shadow: none; } } - .location-text { - font-style: normal; + .location-badge { + font-size: 12px; + margin: -4px 4px -4px -4px; + line-height: 25px; + padding: 4px 8px; + border-radius: $border-radius-default 0 0 $border-radius-default; + transition: border-color ease-in-out $default-transition-duration; } .search-input { @@ -56,59 +62,36 @@ input[type="checkbox"]:hover { margin-left: 5px; line-height: 25px; width: 98%; + color: $white-light; + background: none; + transition: color ease-in-out $default-transition-duration; } - .location-badge { - line-height: 25px; - padding: 0 5px; - border-radius: $border-radius-default; - font-size: 14px; - font-style: normal; - color: $note-disabled-comment-color; - display: inline-block; - background-color: $gray-normal; - vertical-align: top; - cursor: default; + .search-input::placeholder { + transition: color ease-in-out $default-transition-duration; } .search-input-container { - display: -webkit-flex; display: flex; position: relative; } .search-input-wrap { - // Fallback if flexbox is not supported - display: inline-block; - } - - .search-input-wrap { - width: 100%; - .search-icon, .clear-icon { position: absolute; right: 5px; - top: 0; - color: $location-icon-color; - - &::before { - font-family: FontAwesome; - font-weight: $gl-font-weight-normal; - font-style: normal; - } + top: 4px; } .search-icon { - @extend .fa-search; - transition: color 0.15s; + transition: color $default-transition-duration; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; } .clear-icon { - @extend .fa-times; display: none; } @@ -148,21 +131,32 @@ input[type="checkbox"]:hover { form { @extend .form-control:focus; border-color: $dropdown-input-focus-border; - box-shadow: 0 0 4px $search-input-focus-shadow-color; - } + box-shadow: none; + + .search-input-wrap { + .search-icon, + .clear-icon { + color: $gl-text-color-tertiary; + transition: color ease-in-out $default-transition-duration; + } + } - .location-badge { - transition: all 0.15s; - background-color: $location-badge-active-bg; - color: $white-light; - } + .search-input { + color: $gl-text-color; + transition: color ease-in-out $default-transition-duration; + } - .search-input-wrap { - i { - color: $layout-link-gray; + .search-input::placeholder { + color: $gl-text-color-tertiary; } } + .location-badge { + transition: all $default-transition-duration; + background-color: $nav-badge-bg; + border-color: $border-color; + } + .dropdown-menu { transition-duration: 100ms, 75ms; transition-delay: 75ms, 100ms; diff --git a/app/assets/stylesheets/pages/settings_ci_cd.scss b/app/assets/stylesheets/pages/settings_ci_cd.scss index fe22d186af1..a355e2dee24 100644 --- a/app/assets/stylesheets/pages/settings_ci_cd.scss +++ b/app/assets/stylesheets/pages/settings_ci_cd.scss @@ -12,3 +12,7 @@ margin-left: 10px; } } + +.registry-placeholder { + min-height: 60px; +} diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss index 36f622db136..25c80e1f950 100644 --- a/app/assets/stylesheets/pages/status.scss +++ b/app/assets/stylesheets/pages/status.scss @@ -18,7 +18,7 @@ } &.ci-failed { - @include status-color($red-50, $red-500, $red-600); + @include status-color($red-100, $red-500, $red-600); } &.ci-success { @@ -39,12 +39,12 @@ &.ci-pending, &.ci-failed_with_warnings, &.ci-success_with_warnings { - @include status-color($orange-50, $orange-500, $orange-700); + @include status-color($orange-100, $orange-500, $orange-700); } &.ci-info, &.ci-running { - @include status-color($blue-50, $blue-500, $blue-600); + @include status-color($blue-100, $blue-500, $blue-600); } &.ci-created, diff --git a/app/assets/stylesheets/test.scss b/app/assets/stylesheets/test.scss index 7d9f3da79c5..06733b7f1a9 100644 --- a/app/assets/stylesheets/test.scss +++ b/app/assets/stylesheets/test.scss @@ -15,3 +15,9 @@ -ms-animation: none !important; animation: none !important; } + +// Disable sticky changes bar for tests +.diff-files-changed { + position: relative !important; + top: 0 !important; +} diff --git a/app/controllers/admin/applications_controller.rb b/app/controllers/admin/applications_controller.rb index 16590e66d61..fb6d8c0bb81 100644 --- a/app/controllers/admin/applications_controller.rb +++ b/app/controllers/admin/applications_controller.rb @@ -22,8 +22,7 @@ class Admin::ApplicationsController < Admin::ApplicationController @application = Doorkeeper::Application.new(application_params) if @application.save - flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create]) - redirect_to admin_application_url(@application) + redirect_to_admin_page else render :new end @@ -42,6 +41,13 @@ class Admin::ApplicationsController < Admin::ApplicationController redirect_to admin_applications_url, status: 302, notice: 'Application was successfully destroyed.' end + protected + + def redirect_to_admin_page + flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create]) + redirect_to admin_application_url(@application) + end + private def set_application diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index abf03622b17..156a8e2c515 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -128,7 +128,7 @@ class Admin::UsersController < Admin::ApplicationController end respond_to do |format| - result = Users::UpdateService.new(user, user_params_with_pass).execute do |user| + result = Users::UpdateService.new(current_user, user_params_with_pass.merge(user: user)).execute do |user| user.skip_reconfirmation! end @@ -155,7 +155,7 @@ class Admin::UsersController < Admin::ApplicationController def remove_email email = user.emails.find(params[:email_id]) - success = Emails::DestroyService.new(user).execute(email) + success = Emails::DestroyService.new(current_user, user: user).execute(email) respond_to do |format| if success @@ -219,7 +219,7 @@ class Admin::UsersController < Admin::ApplicationController end def update_user(&block) - result = Users::UpdateService.new(user).execute(&block) + result = Users::UpdateService.new(current_user, user: user).execute(&block) result[:status] == :success end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 97922e39ba8..967fe39256a 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -25,6 +25,8 @@ class ApplicationController < ActionController::Base around_action :set_locale + after_action :set_page_title_header, if: -> { request.format == :json } + protect_from_forgery with: :exception helper_method :can?, :current_application_settings @@ -83,12 +85,21 @@ class ApplicationController < ActionController::Base super payload[:remote_ip] = request.remote_ip - if current_user.present? - payload[:user_id] = current_user.id - payload[:username] = current_user.username + logged_user = auth_user + + if logged_user.present? + payload[:user_id] = logged_user.try(:id) + payload[:username] = logged_user.try(:username) end end + # Controllers such as GitHttpController may use alternative methods + # (e.g. tokens) to authenticate the user, whereas Devise sets current_user + def auth_user + return current_user if current_user.present? + return try(:authenticated_user) + end + # This filter handles both private tokens and personal access tokens def authenticate_user_from_private_token! token = params[:private_token].presence || request.headers['PRIVATE-TOKEN'].presence @@ -335,4 +346,9 @@ class ApplicationController < ActionController::Base sign_in user, store: false end end + + def set_page_title_header + # Per https://tools.ietf.org/html/rfc5987, headers need to be ISO-8859-1, not UTF-8 + response.headers['Page-Title'] = page_title('GitLab').encode('ISO-8859-1') + end end diff --git a/app/controllers/concerns/authenticates_with_two_factor.rb b/app/controllers/concerns/authenticates_with_two_factor.rb index b75e401a8df..db8c362f125 100644 --- a/app/controllers/concerns/authenticates_with_two_factor.rb +++ b/app/controllers/concerns/authenticates_with_two_factor.rb @@ -59,6 +59,7 @@ module AuthenticatesWithTwoFactor sign_in(user) else user.increment_failed_attempts! + Gitlab::AppLogger.info("Failed Login: user=#{user.username} ip=#{request.remote_ip} method=OTP") flash.now[:alert] = 'Invalid two-factor code.' prompt_for_two_factor(user) end @@ -75,6 +76,7 @@ module AuthenticatesWithTwoFactor sign_in(user) else user.increment_failed_attempts! + Gitlab::AppLogger.info("Failed Login: user=#{user.username} ip=#{request.remote_ip} method=U2F") flash.now[:alert] = 'Authentication via U2F device failed.' prompt_for_two_factor(user) end diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb index 0d0e53d4b76..3181f517087 100644 --- a/app/controllers/concerns/issuable_collections.rb +++ b/app/controllers/concerns/issuable_collections.rb @@ -106,7 +106,7 @@ module IssuableCollections # @filter_params[:authorized_only] = true end - @filter_params + @filter_params.permit(IssuableFinder::VALID_PARAMS) end def set_default_state @@ -117,19 +117,32 @@ module IssuableCollections key = 'issuable_sort' cookies[key] = params[:sort] if params[:sort].present? - - # id_desc and id_asc are old values for these two. - cookies[key] = sort_value_recently_created if cookies[key] == 'id_desc' - cookies[key] = sort_value_oldest_created if cookies[key] == 'id_asc' - + cookies[key] = update_cookie_value(cookies[key]) params[:sort] = cookies[key] end def default_sort_order case params[:state] - when 'opened', 'all' then sort_value_recently_created + when 'opened', 'all' then sort_value_created_date when 'merged', 'closed' then sort_value_recently_updated - else sort_value_recently_created + else sort_value_created_date + end + end + + # Update old values to the actual ones. + def update_cookie_value(value) + case value + when 'id_asc' then sort_value_oldest_created + when 'id_desc' then sort_value_recently_created + when 'created_asc' then sort_value_created_date + when 'created_desc' then sort_value_created_date + when 'due_date_asc' then sort_value_due_date + when 'due_date_desc' then sort_value_due_date + when 'milestone_due_asc' then sort_value_milestone + when 'milestone_due_desc' then sort_value_milestone + when 'downvotes_asc' then sort_value_popularity + when 'downvotes_desc' then sort_value_popularity + else value end end end diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb index 18fd8eb114d..915f32b4c33 100644 --- a/app/controllers/concerns/notes_actions.rb +++ b/app/controllers/concerns/notes_actions.rb @@ -15,9 +15,9 @@ module NotesActions notes = notes_finder.execute .inc_relations_for_view - .reject { |n| n.cross_reference_not_visible_for?(current_user) } notes = prepare_notes_for_rendering(notes) + notes = notes.reject { |n| n.cross_reference_not_visible_for?(current_user) } notes_json[:notes] = if noteable.discussions_rendered_on_frontend? diff --git a/app/controllers/confirmations_controller.rb b/app/controllers/confirmations_controller.rb index 62ee9470704..80ab681ed87 100644 --- a/app/controllers/confirmations_controller.rb +++ b/app/controllers/confirmations_controller.rb @@ -13,10 +13,15 @@ class ConfirmationsController < Devise::ConfirmationsController def after_confirmation_path_for(_resource_name, resource) # incoming resource can either be a :user or an :email if signed_in?(:user) - after_sign_in_path_for(resource) + after_sign_in(resource) else + Gitlab::AppLogger.info("Email Confirmed: username=#{resource.username} email=#{resource.email} ip=#{request.remote_ip}") flash[:notice] += " Please sign in." new_session_path(:user) end end + + def after_sign_in(resource) + after_sign_in_path_for(resource) + end end diff --git a/app/controllers/oauth/applications_controller.rb b/app/controllers/oauth/applications_controller.rb index 2ae4785b12c..b02e64a132b 100644 --- a/app/controllers/oauth/applications_controller.rb +++ b/app/controllers/oauth/applications_controller.rb @@ -21,14 +21,20 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController @application.owner = current_user if @application.save - flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create]) - redirect_to oauth_application_url(@application) + redirect_to_oauth_application_page else set_index_vars render :index end end + protected + + def redirect_to_oauth_application_page + flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create]) + redirect_to oauth_application_url(@application) + end + private def verify_user_oauth_applications_enabled diff --git a/app/controllers/profiles/avatars_controller.rb b/app/controllers/profiles/avatars_controller.rb index 408650aac54..39b9f8a84d1 100644 --- a/app/controllers/profiles/avatars_controller.rb +++ b/app/controllers/profiles/avatars_controller.rb @@ -2,7 +2,7 @@ class Profiles::AvatarsController < Profiles::ApplicationController def destroy @user = current_user - Users::UpdateService.new(@user).execute { |user| user.remove_avatar! } + Users::UpdateService.new(current_user, user: @user).execute { |user| user.remove_avatar! } redirect_to profile_path, status: 302 end diff --git a/app/controllers/profiles/emails_controller.rb b/app/controllers/profiles/emails_controller.rb index 3ffe5729c2c..bbd7ba49d77 100644 --- a/app/controllers/profiles/emails_controller.rb +++ b/app/controllers/profiles/emails_controller.rb @@ -7,7 +7,7 @@ class Profiles::EmailsController < Profiles::ApplicationController end def create - @email = Emails::CreateService.new(current_user, email_params).execute + @email = Emails::CreateService.new(current_user, email_params.merge(user: current_user)).execute unless @email.errors.blank? flash[:alert] = @email.errors.full_messages.first end @@ -16,7 +16,7 @@ class Profiles::EmailsController < Profiles::ApplicationController end def destroy - Emails::DestroyService.new(current_user).execute(@email) + Emails::DestroyService.new(current_user, user: current_user).execute(@email) respond_to do |format| format.html { redirect_to profile_emails_url, status: 302 } @@ -25,7 +25,7 @@ class Profiles::EmailsController < Profiles::ApplicationController end def resend_confirmation_instructions - if Emails::ConfirmService.new(current_user).execute(@email) + if Emails::ConfirmService.new(current_user, user: current_user).execute(@email) flash[:notice] = "Confirmation email sent to #{@email.email}" else flash[:alert] = "There was a problem sending the confirmation email" diff --git a/app/controllers/profiles/keys_controller.rb b/app/controllers/profiles/keys_controller.rb index 89d6d7f1b52..069e6a810f2 100644 --- a/app/controllers/profiles/keys_controller.rb +++ b/app/controllers/profiles/keys_controller.rb @@ -14,7 +14,7 @@ class Profiles::KeysController < Profiles::ApplicationController @key = Keys::CreateService.new(current_user, key_params).execute if @key.persisted? - redirect_to profile_key_path(@key) + redirect_to_profile_key_path else @keys = current_user.keys.select(&:persisted?) render :index @@ -50,6 +50,12 @@ class Profiles::KeysController < Profiles::ApplicationController end end + protected + + def redirect_to_profile_key_path + redirect_to profile_key_path(@key) + end + private def key_params diff --git a/app/controllers/profiles/notifications_controller.rb b/app/controllers/profiles/notifications_controller.rb index 960b7512602..8a38ba65d4c 100644 --- a/app/controllers/profiles/notifications_controller.rb +++ b/app/controllers/profiles/notifications_controller.rb @@ -7,7 +7,7 @@ class Profiles::NotificationsController < Profiles::ApplicationController end def update - result = Users::UpdateService.new(current_user, user_params).execute + result = Users::UpdateService.new(current_user, user_params.merge(user: current_user)).execute if result[:status] == :success flash[:notice] = "Notification settings saved" diff --git a/app/controllers/profiles/passwords_controller.rb b/app/controllers/profiles/passwords_controller.rb index 7beb52dd8e8..dcfcb855ab5 100644 --- a/app/controllers/profiles/passwords_controller.rb +++ b/app/controllers/profiles/passwords_controller.rb @@ -21,10 +21,10 @@ class Profiles::PasswordsController < Profiles::ApplicationController password_automatically_set: false } - result = Users::UpdateService.new(@user, password_attributes).execute + result = Users::UpdateService.new(current_user, password_attributes.merge(user: @user)).execute if result[:status] == :success - Users::UpdateService.new(@user, password_expires_at: nil).execute + Users::UpdateService.new(current_user, user: @user, password_expires_at: nil).execute redirect_to root_path, notice: 'Password successfully changed' else @@ -46,7 +46,7 @@ class Profiles::PasswordsController < Profiles::ApplicationController return end - result = Users::UpdateService.new(@user, password_attributes).execute + result = Users::UpdateService.new(current_user, password_attributes.merge(user: @user)).execute if result[:status] == :success flash[:notice] = "Password was successfully updated. Please login with it" diff --git a/app/controllers/profiles/personal_access_tokens_controller.rb b/app/controllers/profiles/personal_access_tokens_controller.rb index c1cc509a748..4146deefa89 100644 --- a/app/controllers/profiles/personal_access_tokens_controller.rb +++ b/app/controllers/profiles/personal_access_tokens_controller.rb @@ -1,6 +1,7 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController def index set_index_vars + @personal_access_token = finder.build end def create @@ -40,7 +41,6 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController def set_index_vars @scopes = Gitlab::Auth.available_scopes - @personal_access_token = finder.build @inactive_personal_access_tokens = finder(state: 'inactive').execute @active_personal_access_tokens = finder(state: 'active').execute.order(:expires_at) end diff --git a/app/controllers/profiles/preferences_controller.rb b/app/controllers/profiles/preferences_controller.rb index cce2a847b53..ed0f98179eb 100644 --- a/app/controllers/profiles/preferences_controller.rb +++ b/app/controllers/profiles/preferences_controller.rb @@ -6,7 +6,7 @@ class Profiles::PreferencesController < Profiles::ApplicationController def update begin - result = Users::UpdateService.new(user, preferences_params).execute + result = Users::UpdateService.new(current_user, preferences_params.merge(user: user)).execute if result[:status] == :success flash[:notice] = 'Preferences saved.' diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb index 1a4f77639e7..aa9789f8a0f 100644 --- a/app/controllers/profiles/two_factor_auths_controller.rb +++ b/app/controllers/profiles/two_factor_auths_controller.rb @@ -10,7 +10,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController current_user.otp_grace_period_started_at = Time.current end - Users::UpdateService.new(current_user).execute! + Users::UpdateService.new(current_user, user: current_user).execute! if two_factor_authentication_required? && !current_user.two_factor_enabled? two_factor_authentication_reason( @@ -41,7 +41,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController def create if current_user.validate_and_consume_otp!(params[:pin_code]) - Users::UpdateService.new(current_user, otp_required_for_login: true).execute! do |user| + Users::UpdateService.new(current_user, user: current_user, otp_required_for_login: true).execute! do |user| @codes = user.generate_otp_backup_codes! end @@ -70,7 +70,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController end def codes - Users::UpdateService.new(current_user).execute! do |user| + Users::UpdateService.new(current_user, user: current_user).execute! do |user| @codes = user.generate_otp_backup_codes! end end diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index d83824fef06..5d87037f012 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -10,7 +10,7 @@ class ProfilesController < Profiles::ApplicationController def update respond_to do |format| - result = Users::UpdateService.new(@user, user_params).execute + result = Users::UpdateService.new(current_user, user_params.merge(user: @user)).execute if result[:status] == :success message = "Profile was successfully updated" @@ -25,7 +25,7 @@ class ProfilesController < Profiles::ApplicationController end def reset_private_token - Users::UpdateService.new(@user).execute! do |user| + Users::UpdateService.new(current_user, user: @user).execute! do |user| user.reset_authentication_token! end @@ -35,7 +35,7 @@ class ProfilesController < Profiles::ApplicationController end def reset_incoming_email_token - Users::UpdateService.new(@user).execute! do |user| + Users::UpdateService.new(current_user, user: @user).execute! do |user| user.reset_incoming_email_token! end @@ -45,7 +45,7 @@ class ProfilesController < Profiles::ApplicationController end def reset_rss_token - Users::UpdateService.new(@user).execute! do |user| + Users::UpdateService.new(current_user, user: @user).execute! do |user| user.reset_rss_token! end @@ -61,7 +61,7 @@ class ProfilesController < Profiles::ApplicationController end def update_username - result = Users::UpdateService.new(@user, username: user_params[:username]).execute + result = Users::UpdateService.new(current_user, user: @user, username: user_params[:username]).execute options = if result[:status] == :success { notice: "Username successfully changed" } diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index 2b8f3977e6e..183a6f88a6a 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -41,6 +41,8 @@ class Projects::BlobController < Projects::ApplicationController end format.json do + page_title @blob.path, @ref, @project.name_with_namespace + show_json end end diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index a9cce578366..7f03ce07dec 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -9,7 +9,7 @@ class Projects::BranchesController < Projects::ApplicationController def index @sort = params[:sort].presence || sort_value_recently_updated - @branches = BranchesFinder.new(@repository, params).execute + @branches = BranchesFinder.new(@repository, params.merge(sort: @sort)).execute @branches = Kaminari.paginate_array(@branches).page(params[:page]) respond_to do |format| diff --git a/app/controllers/projects/git_http_client_controller.rb b/app/controllers/projects/git_http_client_controller.rb index 7d0e2b3e2ef..95d7a02e9e9 100644 --- a/app/controllers/projects/git_http_client_controller.rb +++ b/app/controllers/projects/git_http_client_controller.rb @@ -9,6 +9,7 @@ class Projects::GitHttpClientController < Projects::ApplicationController delegate :actor, :authentication_abilities, to: :authentication_result, allow_nil: true alias_method :user, :actor + alias_method :authenticated_user, :actor # Git clients will not know what authenticity token to send along skip_before_action :verify_authenticity_token diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index a3ec79a56d9..ee6e6f80cdd 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -16,7 +16,7 @@ class Projects::IssuesController < Projects::ApplicationController before_action :authorize_create_issue!, only: [:new, :create] # Allow modify issue - before_action :authorize_update_issue!, only: [:edit, :update, :move] + before_action :authorize_update_issue!, only: [:update, :move] # Allow create a new branch and empty WIP merge request from current issue before_action :authorize_create_merge_request!, only: [:create_merge_request] @@ -63,10 +63,6 @@ class Projects::IssuesController < Projects::ApplicationController respond_with(@issue) end - def edit - respond_with(@issue) - end - def show @noteable = @issue @note = @project.notes.new(noteable: @issue) @@ -126,10 +122,6 @@ class Projects::IssuesController < Projects::ApplicationController @issue = Issues::UpdateService.new(project, current_user, update_params).execute(issue) respond_to do |format| - format.html do - recaptcha_check_with_fallback { render :edit } - end - format.json do render_issue_json end diff --git a/app/controllers/projects/registry/repositories_controller.rb b/app/controllers/projects/registry/repositories_controller.rb index 71e7dc70a4d..32c0fc6d14a 100644 --- a/app/controllers/projects/registry/repositories_controller.rb +++ b/app/controllers/projects/registry/repositories_controller.rb @@ -6,17 +6,26 @@ module Projects def index @images = project.container_repositories + + respond_to do |format| + format.html + format.json do + render json: ContainerRepositoriesSerializer + .new(project: project, current_user: current_user) + .represent(@images) + end + end end def destroy if image.destroy - redirect_to project_container_registry_index_path(@project), - status: 302, - notice: 'Image repository has been removed successfully!' + respond_to do |format| + format.json { head :no_content } + end else - redirect_to project_container_registry_index_path(@project), - status: 302, - alert: 'Failed to remove image repository!' + respond_to do |format| + format.json { head :bad_request } + end end end diff --git a/app/controllers/projects/registry/tags_controller.rb b/app/controllers/projects/registry/tags_controller.rb index ae72bd03cfb..e602aa3f393 100644 --- a/app/controllers/projects/registry/tags_controller.rb +++ b/app/controllers/projects/registry/tags_controller.rb @@ -3,20 +3,35 @@ module Projects class TagsController < ::Projects::Registry::ApplicationController before_action :authorize_update_container_image!, only: [:destroy] + def index + respond_to do |format| + format.json do + render json: ContainerTagsSerializer + .new(project: @project, current_user: @current_user) + .with_pagination(request, response) + .represent(tags) + end + end + end + def destroy if tag.delete - redirect_to project_container_registry_index_path(@project), - status: 302, - notice: 'Registry tag has been removed successfully!' + respond_to do |format| + format.json { head :no_content } + end else - redirect_to project_container_registry_index_path(@project), - status: 302, - alert: 'Failed to remove registry tag!' + respond_to do |format| + format.json { head :bad_request } + end end end private + def tags + Kaminari::PaginatableArray.new(image.tags, limit: 15) + end + def image @image ||= project.container_repositories .find(params[:repository_id]) diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb index f3784f4e07c..f3719059f88 100644 --- a/app/controllers/projects/tree_controller.rb +++ b/app/controllers/projects/tree_controller.rb @@ -35,6 +35,8 @@ class Projects::TreeController < Projects::ApplicationController end format.json do + page_title @path.presence || _("Files"), @ref, @project.name_with_namespace + # n+1: https://gitlab.com/gitlab-org/gitlab-ce/issues/38261 Gitlab::GitalyClient.allow_n_plus_1_calls do render json: TreeSerializer.new(project: @project, repository: @repository, ref: @ref).represent(@tree) diff --git a/app/controllers/projects/wikis_controller.rb b/app/controllers/projects/wikis_controller.rb index 968d880886c..a8ebdf5a4a9 100644 --- a/app/controllers/projects/wikis_controller.rb +++ b/app/controllers/projects/wikis_controller.rb @@ -18,16 +18,12 @@ class Projects::WikisController < Projects::ApplicationController response.headers['Content-Security-Policy'] = "default-src 'none'" response.headers['X-Content-Security-Policy'] = "default-src 'none'" - if file.on_disk? - send_file file.on_disk_path, disposition: 'inline' - else - send_data( - file.raw_data, - type: file.mime_type, - disposition: 'inline', - filename: file.name - ) - end + send_data( + file.raw_data, + type: file.mime_type, + disposition: 'inline', + filename: file.name + ) else return render('empty') unless can?(current_user, :create_wiki, @project) @page = WikiPage.new(@project_wiki) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index b13034d3333..a738ca9f361 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -344,6 +344,7 @@ class ProjectsController < Projects::ApplicationController :tag_list, :visibility_level, :template_name, + :merge_method, project_feature_attributes: %i[ builds_access_level diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 1bc6520370a..5ea3a5d5562 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -42,10 +42,12 @@ class RegistrationsController < Devise::RegistrationsController end def after_sign_up_path_for(user) + Gitlab::AppLogger.info("User Created: username=#{user.username} email=#{user.email} ip=#{request.remote_ip} confirmed:#{user.confirmed?}") user.confirmed? ? dashboard_projects_path : users_almost_there_path end - def after_inactive_sign_up_path_for(_resource) + def after_inactive_sign_up_path_for(resource) + Gitlab::AppLogger.info("User Created: username=#{resource.username} email=#{resource.email} ip=#{request.remote_ip} confirmed:false") users_almost_there_path end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index be6491d042c..4223c6171a6 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -13,6 +13,8 @@ class SessionsController < Devise::SessionsController before_action :auto_sign_in_with_provider, only: [:new] before_action :load_recaptcha + after_action :log_failed_login, only: [:new] + def new set_minimum_password_length @ldap_servers = Gitlab::LDAP::Config.available_servers @@ -29,12 +31,13 @@ class SessionsController < Devise::SessionsController end # hide the signed-in notification flash[:notice] = nil - log_audit_event(current_user, with: authentication_method) + log_audit_event(current_user, resource, with: authentication_method) log_user_activity(current_user) end end def destroy + Gitlab::AppLogger.info("User Logout: username=#{current_user.username} ip=#{request.remote_ip}") super # hide the signed_out notice flash[:notice] = nil @@ -42,6 +45,16 @@ class SessionsController < Devise::SessionsController private + def log_failed_login + return unless failed_login? + + Gitlab::AppLogger.info("Failed Login: username=#{user_params[:login]} ip=#{request.remote_ip}") + end + + def failed_login? + (options = env["warden.options"]) && options[:action] == "unauthenticated" + end + def login_counter @login_counter ||= Gitlab::Metrics.counter(:user_session_logins_total, 'User sign in count') end @@ -55,7 +68,7 @@ class SessionsController < Devise::SessionsController return unless user && user.require_password_creation? - Users::UpdateService.new(user).execute do |user| + Users::UpdateService.new(current_user, user: user).execute do |user| @token = user.generate_reset_token end @@ -123,7 +136,8 @@ class SessionsController < Devise::SessionsController user.invalidate_otp_backup_code!(user_params[:otp_attempt]) end - def log_audit_event(user, options = {}) + def log_audit_event(user, resource, options = {}) + Gitlab::AppLogger.info("Successful Login: username=#{resource.username} ip=#{request.remote_ip} method=#{options[:with]} admin=#{resource.admin?}") AuditEventService.new(user, user, options) .for_authentication.security_event end diff --git a/app/finders/concerns/custom_attributes_filter.rb b/app/finders/concerns/custom_attributes_filter.rb new file mode 100644 index 00000000000..5bbf9ca242d --- /dev/null +++ b/app/finders/concerns/custom_attributes_filter.rb @@ -0,0 +1,20 @@ +module CustomAttributesFilter + def by_custom_attributes(items) + return items unless params[:custom_attributes].is_a?(Hash) + return items unless Ability.allowed?(current_user, :read_custom_attribute) + + association = items.reflect_on_association(:custom_attributes) + attributes_table = association.klass.arel_table + attributable_table = items.model.arel_table + + custom_attributes = association.klass.select('true').where( + attributes_table[association.foreign_key] + .eq(attributable_table[association.association_primary_key]) + ) + + # perform a subquery for each attribute to be filtered + params[:custom_attributes].inject(items) do |scope, (key, value)| + scope.where('EXISTS (?)', custom_attributes.where(key: key, value: value)) + end + end +end diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb index 0a2e3c709d9..24c07f3dc70 100644 --- a/app/finders/issuable_finder.rb +++ b/app/finders/issuable_finder.rb @@ -25,6 +25,28 @@ class IssuableFinder NONE = '0'.freeze + SCALAR_PARAMS = %i[ + assignee_id + assignee_username + author_id + author_username + authorized_only + due_date + group_id + iids + label_name + milestone_title + non_archived + project_id + scope + search + sort + state + ].freeze + ARRAY_PARAMS = { label_name: [], iids: [], assignee_username: [] }.freeze + + VALID_PARAMS = (SCALAR_PARAMS + [ARRAY_PARAMS]).freeze + attr_accessor :current_user, :params def initialize(current_user, params = {}) diff --git a/app/finders/users_finder.rb b/app/finders/users_finder.rb index 33f7ae90598..1a7e97004fb 100644 --- a/app/finders/users_finder.rb +++ b/app/finders/users_finder.rb @@ -15,6 +15,7 @@ # class UsersFinder include CreatedAtFilter + include CustomAttributesFilter attr_accessor :current_user, :params @@ -32,6 +33,7 @@ class UsersFinder users = by_external_identity(users) users = by_external(users) users = by_created_at(users) + users = by_custom_attributes(users) users end diff --git a/app/helpers/avatars_helper.rb b/app/helpers/avatars_helper.rb index a4c226a6aad..be11d453898 100644 --- a/app/helpers/avatars_helper.rb +++ b/app/helpers/avatars_helper.rb @@ -13,22 +13,29 @@ module AvatarsHelper user_name = options[:user].try(:name) || options[:user_name] avatar_url = options[:url] || avatar_icon(options[:user] || options[:user_email], avatar_size) has_tooltip = options[:has_tooltip].nil? ? true : options[:has_tooltip] - data_attributes = {} + data_attributes = options[:data] || {} css_class = %W[avatar s#{avatar_size}].push(*options[:css_class]) if has_tooltip css_class.push('has-tooltip') - data_attributes = { container: 'body' } + data_attributes[:container] = 'body' end - image_tag( - avatar_url, + if options[:lazy] + css_class << 'lazy' + data_attributes[:src] = avatar_url + avatar_url = LazyImageTagHelper.placeholder_image + end + + image_options = { + alt: "#{user_name}'s avatar", + src: avatar_url, + data: data_attributes, class: css_class, - alt: "#{user_name}'s avatar", - title: user_name, - data: data_attributes, - lazy: true - ) + title: user_name + } + + tag(:img, image_options) end def user_avatar(options = {}) diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb index 62ac208f16a..7112c6ee470 100644 --- a/app/helpers/boards_helper.rb +++ b/app/helpers/boards_helper.rb @@ -79,6 +79,6 @@ module BoardsHelper end def boards_link_text - _("Board") + s_("IssueBoards|Board") end end diff --git a/app/helpers/breadcrumbs_helper.rb b/app/helpers/breadcrumbs_helper.rb index ee1b7ed083e..e88fe6bcd7e 100644 --- a/app/helpers/breadcrumbs_helper.rb +++ b/app/helpers/breadcrumbs_helper.rb @@ -10,11 +10,7 @@ module BreadcrumbsHelper def breadcrumb_title_link return @breadcrumb_link if @breadcrumb_link - if controller.available_action?(:index) - url_for(action: "index") - else - request.path - end + request.path end def breadcrumb_title(title) @@ -25,7 +21,7 @@ module BreadcrumbsHelper def breadcrumb_list_item(link) content_tag "li" do - link + icon("angle-right", class: "breadcrumbs-list-angle") + link + sprite_icon("angle-right", size: 8, css_class: "breadcrumbs-list-angle") end end diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index 28f591a4e22..4e4a66e8a02 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -33,19 +33,21 @@ module DiffHelper end def diff_match_line(old_pos, new_pos, text: '', view: :inline, bottom: false) - content = content_tag :td, text, class: "line_content match #{view == :inline ? '' : view}" - cls = ['diff-line-num', 'unfold', 'js-unfold'] - cls << 'js-unfold-bottom' if bottom + content_line_class = %w[line_content match] + content_line_class << 'parallel' if view == :parallel + + line_num_class = %w[diff-line-num unfold js-unfold] + line_num_class << 'js-unfold-bottom' if bottom html = '' if old_pos - html << content_tag(:td, '...', class: cls + ['old_line'], data: { linenumber: old_pos }) - html << content unless view == :inline + html << content_tag(:td, '...', class: [*line_num_class, 'old_line'], data: { linenumber: old_pos }) + html << content_tag(:td, text, class: [*content_line_class, 'left-side']) if view == :parallel end if new_pos - html << content_tag(:td, '...', class: cls + ['new_line'], data: { linenumber: new_pos }) - html << content + html << content_tag(:td, '...', class: [*line_num_class, 'new_line'], data: { linenumber: new_pos }) + html << content_tag(:td, text, class: [*content_line_class, ('right-side' if view == :parallel)]) end html.html_safe diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb index b331693c789..fd88e0d794a 100644 --- a/app/helpers/events_helper.rb +++ b/app/helpers/events_helper.rb @@ -1,13 +1,15 @@ module EventsHelper ICON_NAMES_BY_EVENT_TYPE = { - 'pushed to' => 'icon_commit', - 'pushed new' => 'icon_commit', - 'created' => 'icon_status_open', - 'opened' => 'icon_status_open', - 'closed' => 'icon_status_closed', - 'accepted' => 'icon_code_fork', - 'commented on' => 'icon_comment_o', - 'deleted' => 'icon_trash_o' + 'pushed to' => 'commit', + 'pushed new' => 'commit', + 'created' => 'status_open', + 'opened' => 'status_open', + 'closed' => 'status_closed', + 'accepted' => 'fork', + 'commented on' => 'comment', + 'deleted' => 'remove', + 'imported' => 'import', + 'joined' => 'users' }.freeze def link_to_author(event, self_added: false) @@ -197,7 +199,7 @@ module EventsHelper def icon_for_event(note) icon_name = ICON_NAMES_BY_EVENT_TYPE[note] - custom_icon(icon_name) if icon_name + sprite_icon(icon_name) if icon_name end def icon_for_profile_event(event) diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb index 08e6443bd0f..ec779c1c447 100644 --- a/app/helpers/icons_helper.rb +++ b/app/helpers/icons_helper.rb @@ -24,9 +24,9 @@ module IconsHelper end def sprite_icon(icon_name, size: nil, css_class: nil) - css_classes = size ? "s#{size}" : nil + css_classes = size ? "s#{size}" : "" css_classes << " #{css_class}" unless css_class.blank? - content_tag(:svg, content_tag(:use, "", { "xlink:href" => "#{image_path('icons.svg')}##{icon_name}" } ), class: css_classes) + content_tag(:svg, content_tag(:use, "", { "xlink:href" => "#{image_path('icons.svg')}##{icon_name}" } ), class: css_classes.empty? ? nil : css_classes) end def audit_icon(names, options = {}) diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index df390dd5aab..7713fb0b9f8 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -248,16 +248,25 @@ module IssuablesHelper Gitlab::IssuablesCountForState.new(finder)[state] end - def close_issuable_url(issuable) - issuable_url(issuable, close_reopen_params(issuable, :close)) + def close_issuable_path(issuable) + issuable_path(issuable, close_reopen_params(issuable, :close)) end - def reopen_issuable_url(issuable) - issuable_url(issuable, close_reopen_params(issuable, :reopen)) + def reopen_issuable_path(issuable) + issuable_path(issuable, close_reopen_params(issuable, :reopen)) end - def close_reopen_issuable_url(issuable, should_inverse = false) - issuable.closed? ^ should_inverse ? reopen_issuable_url(issuable) : close_issuable_url(issuable) + def close_reopen_issuable_path(issuable, should_inverse = false) + issuable.closed? ^ should_inverse ? reopen_issuable_path(issuable) : close_issuable_path(issuable) + end + + def issuable_path(issuable, *options) + case issuable + when Issue + issue_path(issuable, *options) + when MergeRequest + merge_request_path(issuable, *options) + end end def issuable_url(issuable, *options) diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb index 5946c475835..18b9bf214a3 100644 --- a/app/helpers/page_layout_helper.rb +++ b/app/helpers/page_layout_helper.rb @@ -9,7 +9,7 @@ module PageLayoutHelper end # Segments are seperated by middot - @page_title.join(" \u00b7 ") + @page_title.join(" · ") end # Define or get a description for the current page diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index ddeff490d3a..4c0cce54527 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -21,11 +21,14 @@ module ProjectsHelper classes = %W[avatar avatar-inline s#{opts[:size]}] classes << opts[:avatar_class] if opts[:avatar_class] - image_tag(avatar_icon(author, opts[:size]), width: opts[:size], class: classes, alt: '') + avatar = avatar_icon(author, opts[:size]) + src = opts[:lazy_load] ? nil : avatar + + image_tag(src, width: opts[:size], class: classes, alt: '', "data-src" => avatar) end def link_to_member(project, author, opts = {}, &block) - default_opts = { avatar: true, name: true, size: 16, author_class: 'author', title: ":name", tooltip: false } + default_opts = { avatar: true, name: true, size: 16, author_class: 'author', title: ":name", tooltip: false, lazy_load: false } opts = default_opts.merge(opts) return "(deleted)" unless author @@ -239,8 +242,8 @@ module ProjectsHelper end end - def has_projects_or_name?(projects, params) - !!(params[:name] || any_projects?(projects)) + def show_projects?(projects, params) + !!(params[:personal] || params[:name] || any_projects?(projects)) end private diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb index c4a73bedbcd..1b542ed2a96 100644 --- a/app/helpers/sorting_helper.rb +++ b/app/helpers/sorting_helper.rb @@ -1,34 +1,38 @@ module SortingHelper def sort_options_hash { - sort_value_name => sort_title_name, - sort_value_name_desc => sort_title_name_desc, - sort_value_recently_updated => sort_title_recently_updated, - sort_value_oldest_updated => sort_title_oldest_updated, + sort_value_created_date => sort_title_created_date, + sort_value_downvotes => sort_title_downvotes, + sort_value_due_date => sort_title_due_date, + sort_value_due_date_later => sort_title_due_date_later, + sort_value_due_date_soon => sort_title_due_date_soon, + sort_value_label_priority => sort_title_label_priority, + sort_value_largest_group => sort_title_largest_group, + sort_value_largest_repo => sort_title_largest_repo, + sort_value_milestone => sort_title_milestone, + sort_value_milestone_later => sort_title_milestone_later, + sort_value_milestone_soon => sort_title_milestone_soon, + sort_value_name => sort_title_name, + sort_value_name_desc => sort_title_name_desc, + sort_value_oldest_created => sort_title_oldest_created, + sort_value_oldest_signin => sort_title_oldest_signin, + sort_value_oldest_updated => sort_title_oldest_updated, sort_value_recently_created => sort_title_recently_created, - sort_value_oldest_created => sort_title_oldest_created, - sort_value_milestone_soon => sort_title_milestone_soon, - sort_value_milestone_later => sort_title_milestone_later, - sort_value_due_date_soon => sort_title_due_date_soon, - sort_value_due_date_later => sort_title_due_date_later, - sort_value_largest_repo => sort_title_largest_repo, - sort_value_largest_group => sort_title_largest_group, - sort_value_recently_signin => sort_title_recently_signin, - sort_value_oldest_signin => sort_title_oldest_signin, - sort_value_downvotes => sort_title_downvotes, - sort_value_upvotes => sort_title_upvotes, - sort_value_priority => sort_title_priority, - sort_value_label_priority => sort_title_label_priority + sort_value_recently_signin => sort_title_recently_signin, + sort_value_recently_updated => sort_title_recently_updated, + sort_value_popularity => sort_title_popularity, + sort_value_priority => sort_title_priority, + sort_value_upvotes => sort_title_upvotes } end def projects_sort_options_hash options = { - sort_value_name => sort_title_name, - sort_value_latest_activity => sort_title_latest_activity, - sort_value_oldest_activity => sort_title_oldest_activity, - sort_value_recently_created => sort_title_recently_created, - sort_value_oldest_created => sort_title_oldest_created + sort_value_latest_activity => sort_title_latest_activity, + sort_value_name => sort_title_name, + sort_value_oldest_activity => sort_title_oldest_activity, + sort_value_oldest_created => sort_title_oldest_created, + sort_value_recently_created => sort_title_recently_created } if current_controller?('admin/projects') @@ -40,160 +44,174 @@ module SortingHelper def member_sort_options_hash { - sort_value_access_level_asc => sort_title_access_level_asc, + sort_value_access_level_asc => sort_title_access_level_asc, sort_value_access_level_desc => sort_title_access_level_desc, - sort_value_last_joined => sort_title_last_joined, - sort_value_oldest_joined => sort_title_oldest_joined, - sort_value_name => sort_title_name_asc, - sort_value_name_desc => sort_title_name_desc, - sort_value_recently_signin => sort_title_recently_signin, - sort_value_oldest_signin => sort_title_oldest_signin + sort_value_last_joined => sort_title_last_joined, + sort_value_name => sort_title_name_asc, + sort_value_name_desc => sort_title_name_desc, + sort_value_oldest_joined => sort_title_oldest_joined, + sort_value_oldest_signin => sort_title_oldest_signin, + sort_value_recently_signin => sort_title_recently_signin } end def milestone_sort_options_hash { - sort_value_name => sort_title_name_asc, - sort_value_name_desc => sort_title_name_desc, - sort_value_due_date_soon => sort_title_due_date_soon, - sort_value_due_date_later => sort_title_due_date_later, - sort_value_start_date_soon => sort_title_start_date_soon, - sort_value_start_date_later => sort_title_start_date_later + sort_value_name => sort_title_name_asc, + sort_value_name_desc => sort_title_name_desc, + sort_value_due_date_later => sort_title_due_date_later, + sort_value_due_date_soon => sort_title_due_date_soon, + sort_value_start_date_later => sort_title_start_date_later, + sort_value_start_date_soon => sort_title_start_date_soon } end def branches_sort_options_hash { - sort_value_name => sort_title_name, - sort_value_recently_updated => sort_title_recently_updated, - sort_value_oldest_updated => sort_title_oldest_updated + sort_value_name => sort_title_name, + sort_value_oldest_updated => sort_title_oldest_updated, + sort_value_recently_updated => sort_title_recently_updated } end def tags_sort_options_hash { - sort_value_name => sort_title_name, - sort_value_recently_updated => sort_title_recently_updated, - sort_value_oldest_updated => sort_title_oldest_updated + sort_value_name => sort_title_name, + sort_value_oldest_updated => sort_title_oldest_updated, + sort_value_recently_updated => sort_title_recently_updated } end - def sort_title_priority - s_('SortOptions|Priority') + def sortable_item(item, path, sorted_by) + link_to item, path, class: sorted_by == item ? 'is-active' : '' end - def sort_title_label_priority - s_('SortOptions|Label priority') + # Titles. + def sort_title_access_level_asc + s_('SortOptions|Access level, ascending') end - def sort_title_oldest_updated - s_('SortOptions|Oldest updated') + def sort_title_access_level_desc + s_('SortOptions|Access level, descending') end - def sort_title_recently_updated - s_('SortOptions|Last updated') + def sort_title_created_date + s_('SortOptions|Created date') end - def sort_title_oldest_activity - s_('SortOptions|Oldest updated') + def sort_title_downvotes + s_('SortOptions|Least popular') end - def sort_title_latest_activity - s_('SortOptions|Last updated') + def sort_title_due_date + s_('SortOptions|Due date') end - def sort_title_oldest_created - s_('SortOptions|Oldest created') + def sort_title_due_date_later + s_('SortOptions|Due later') end - def sort_title_recently_created - s_('SortOptions|Last created') + def sort_title_due_date_soon + s_('SortOptions|Due soon') end - def sort_title_milestone_soon - s_('SortOptions|Milestone due soon') + def sort_title_label_priority + s_('SortOptions|Label priority') end - def sort_title_milestone_later - s_('SortOptions|Milestone due later') + def sort_title_largest_group + s_('SortOptions|Largest group') end - def sort_title_due_date_soon - s_('SortOptions|Due soon') + def sort_title_largest_repo + s_('SortOptions|Largest repository') end - def sort_title_due_date_later - s_('SortOptions|Due later') + def sort_title_last_joined + s_('SortOptions|Last joined') end - def sort_title_start_date_soon - s_('SortOptions|Start soon') + def sort_title_latest_activity + s_('SortOptions|Last updated') end - def sort_title_start_date_later - s_('SortOptions|Start later') + def sort_title_milestone + s_('SortOptions|Milestone') + end + + def sort_title_milestone_later + s_('SortOptions|Milestone due later') + end + + def sort_title_milestone_soon + s_('SortOptions|Milestone due soon') end def sort_title_name s_('SortOptions|Name') end - def sort_title_largest_repo - s_('SortOptions|Largest repository') + def sort_title_name_asc + s_('SortOptions|Name, ascending') end - def sort_title_largest_group - s_('SortOptions|Largest group') + def sort_title_name_desc + s_('SortOptions|Name, descending') end - def sort_title_recently_signin - s_('SortOptions|Recent sign in') + def sort_title_oldest_activity + s_('SortOptions|Oldest updated') end - def sort_title_oldest_signin - s_('SortOptions|Oldest sign in') + def sort_title_oldest_created + s_('SortOptions|Oldest created') end - def sort_title_downvotes - s_('SortOptions|Least popular') + def sort_title_oldest_joined + s_('SortOptions|Oldest joined') end - def sort_title_upvotes - s_('SortOptions|Most popular') + def sort_title_oldest_signin + s_('SortOptions|Oldest sign in') end - def sort_title_last_joined - s_('SortOptions|Last joined') + def sort_title_oldest_updated + s_('SortOptions|Oldest updated') end - def sort_title_oldest_joined - s_('SortOptions|Oldest joined') + def sort_title_popularity + s_('SortOptions|Popularity') end - def sort_title_access_level_asc - s_('SortOptions|Access level, ascending') + def sort_title_priority + s_('SortOptions|Priority') end - def sort_title_access_level_desc - s_('SortOptions|Access level, descending') + def sort_title_recently_created + s_('SortOptions|Last created') end - def sort_title_name_asc - s_('SortOptions|Name, ascending') + def sort_title_recently_signin + s_('SortOptions|Recent sign in') end - def sort_title_name_desc - s_('SortOptions|Name, descending') + def sort_title_recently_updated + s_('SortOptions|Last updated') end - def sort_value_last_joined - 'last_joined' + def sort_title_start_date_later + s_('SortOptions|Start later') end - def sort_value_oldest_joined - 'oldest_joined' + def sort_title_start_date_soon + s_('SortOptions|Start soon') end + def sort_title_upvotes + s_('SortOptions|Most popular') + end + + # Values. def sort_value_access_level_asc 'access_level_asc' end @@ -202,88 +220,112 @@ module SortingHelper 'access_level_desc' end - def sort_value_name_desc - 'name_desc' + def sort_value_created_date + 'created_date' end - def sort_value_priority - 'priority' + def sort_value_downvotes + 'downvotes_desc' + end + + def sort_value_due_date + 'due_date' + end + + def sort_value_due_date_later + 'due_date_desc' + end + + def sort_value_due_date_soon + 'due_date_asc' end def sort_value_label_priority 'label_priority' end - def sort_value_oldest_updated - 'updated_asc' + def sort_value_largest_group + 'storage_size_desc' end - def sort_value_recently_updated - 'updated_desc' + def sort_value_largest_repo + 'storage_size_desc' end - def sort_value_oldest_activity - 'latest_activity_asc' + def sort_value_last_joined + 'last_joined' end def sort_value_latest_activity 'latest_activity_desc' end - def sort_value_oldest_created - 'created_asc' + def sort_value_milestone + 'milestone' end - def sort_value_recently_created - 'created_desc' + def sort_value_milestone_later + 'milestone_due_desc' end def sort_value_milestone_soon 'milestone_due_asc' end - def sort_value_milestone_later - 'milestone_due_desc' + def sort_value_name + 'name_asc' end - def sort_value_due_date_soon - 'due_date_asc' + def sort_value_name_desc + 'name_desc' end - def sort_value_due_date_later - 'due_date_desc' + def sort_value_oldest_activity + 'latest_activity_asc' end - def sort_value_start_date_soon - 'start_date_asc' + def sort_value_oldest_created + 'created_asc' end - def sort_value_start_date_later - 'start_date_desc' + def sort_value_oldest_signin + 'oldest_sign_in' end - def sort_value_name - 'name_asc' + def sort_value_oldest_joined + 'oldest_joined' end - def sort_value_largest_repo - 'storage_size_desc' + def sort_value_oldest_updated + 'updated_asc' end - def sort_value_largest_group - 'storage_size_desc' + def sort_value_popularity + 'popularity' + end + + def sort_value_priority + 'priority' + end + + def sort_value_recently_created + 'created_desc' end def sort_value_recently_signin 'recent_sign_in' end - def sort_value_oldest_signin - 'oldest_sign_in' + def sort_value_recently_updated + 'updated_desc' end - def sort_value_downvotes - 'downvotes_desc' + def sort_value_start_date_later + 'start_date_desc' + end + + def sort_value_start_date_soon + 'start_date_asc' end def sort_value_upvotes diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index ee544d8ac56..dd315866e60 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -229,6 +229,10 @@ module Ci variables end + def features + { trace_sections: true } + end + def merge_request return @merge_request if defined?(@merge_request) diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index acaa028eaa2..3d5acc00f8f 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -434,7 +434,7 @@ module Ci def update_duration return unless started_at - self.duration = Gitlab::Ci::PipelineDuration.from_pipeline(self) + self.duration = Gitlab::Ci::Pipeline::Duration.from_pipeline(self) end def execute_hooks diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb index a0d07902ba2..c6509f89117 100644 --- a/app/models/ci/runner.rb +++ b/app/models/ci/runner.rb @@ -174,7 +174,7 @@ module Ci end def assignable_for?(project) - !locked? || projects.exists?(id: project.id) + is_shared? || projects.exists?(id: project.id) end def accepting_tags?(build) diff --git a/app/models/commit.rb b/app/models/commit.rb index 2ae8890c1b3..6dba154a6ea 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -25,8 +25,8 @@ class Commit DIFF_HARD_LIMIT_FILES = 1000 DIFF_HARD_LIMIT_LINES = 50000 - # The SHA can be between 7 and 40 hex characters. - COMMIT_SHA_PATTERN = '\h{7,40}'.freeze + MIN_SHA_LENGTH = 7 + COMMIT_SHA_PATTERN = /\h{#{MIN_SHA_LENGTH},40}/.freeze def banzai_render_context(field) context = { pipeline: :single_line, project: self.project } @@ -53,7 +53,7 @@ class Commit # Truncate sha to 8 characters def truncate_sha(sha) - sha[0..7] + sha[0..MIN_SHA_LENGTH] end def max_diff_options @@ -100,7 +100,7 @@ class Commit def self.reference_pattern @reference_pattern ||= %r{ (?:#{Project.reference_pattern}#{reference_prefix})? - (?<commit>\h{7,40}) + (?<commit>#{COMMIT_SHA_PATTERN}) }x end @@ -216,9 +216,8 @@ class Commit @raw.respond_to?(method, include_private) || super end - # Truncate sha to 8 characters def short_id - @raw.short_id(7) + @raw.short_id(MIN_SHA_LENGTH) end def diff_refs diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 265f6e48540..fc30d008dea 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -143,16 +143,18 @@ module Issuable end def sort(method, excluded_labels: []) - sorted = case method.to_s - when 'milestone_due_asc' then order_milestone_due_asc - when 'milestone_due_desc' then order_milestone_due_desc - when 'downvotes_desc' then order_downvotes_desc - when 'upvotes_desc' then order_upvotes_desc - when 'label_priority' then order_labels_priority(excluded_labels: excluded_labels) - when 'priority' then order_due_date_and_labels_priority(excluded_labels: excluded_labels) - else - order_by(method) - end + sorted = + case method.to_s + when 'downvotes_desc' then order_downvotes_desc + when 'label_priority' then order_labels_priority(excluded_labels: excluded_labels) + when 'milestone' then order_milestone_due_asc + when 'milestone_due_asc' then order_milestone_due_asc + when 'milestone_due_desc' then order_milestone_due_desc + when 'popularity' then order_upvotes_desc + when 'priority' then order_due_date_and_labels_priority(excluded_labels: excluded_labels) + when 'upvotes_desc' then order_upvotes_desc + else order_by(method) + end # Break ties with the ID column for pagination sorted.order(id: :desc) @@ -214,7 +216,7 @@ module Issuable def grouping_columns(sort) grouping_columns = [arel_table[:id]] - if %w(milestone_due_desc milestone_due_asc).include?(sort) + if %w(milestone_due_desc milestone_due_asc milestone).include?(sort) milestone_table = Milestone.arel_table grouping_columns << milestone_table[:id] grouping_columns << milestone_table[:due_date] diff --git a/app/models/concerns/sortable.rb b/app/models/concerns/sortable.rb index db3cd257584..cefa5c13c5f 100644 --- a/app/models/concerns/sortable.rb +++ b/app/models/concerns/sortable.rb @@ -19,14 +19,15 @@ module Sortable module ClassMethods def order_by(method) case method.to_s - when 'name_asc' then order_name_asc - when 'name_desc' then order_name_desc - when 'updated_asc' then order_updated_asc - when 'updated_desc' then order_updated_desc - when 'created_asc' then order_created_asc + when 'created_asc' then order_created_asc + when 'created_date' then order_created_desc when 'created_desc' then order_created_desc - when 'id_desc' then order_id_desc - when 'id_asc' then order_id_asc + when 'id_asc' then order_id_asc + when 'id_desc' then order_id_desc + when 'name_asc' then order_name_asc + when 'name_desc' then order_name_desc + when 'updated_asc' then order_updated_asc + when 'updated_desc' then order_updated_desc else all end diff --git a/app/models/gpg_key.rb b/app/models/gpg_key.rb index 44deae4234b..54bd5b68777 100644 --- a/app/models/gpg_key.rb +++ b/app/models/gpg_key.rb @@ -73,7 +73,7 @@ class GpgKey < ActiveRecord::Base end def verified_and_belongs_to_email?(email) - emails_with_verified_status.fetch(email, false) + emails_with_verified_status.fetch(email.downcase, false) end def update_invalid_gpg_signatures diff --git a/app/models/issue.rb b/app/models/issue.rb index 92a454300af..155c5d972b7 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -116,7 +116,8 @@ class Issue < ActiveRecord::Base def self.sort(method, excluded_labels: []) case method.to_s - when 'due_date_asc' then order_due_date_asc + when 'due_date' then order_due_date_asc + when 'due_date_asc' then order_due_date_asc when 'due_date_desc' then order_due_date_desc else super diff --git a/app/models/key.rb b/app/models/key.rb index 0c41e34d969..f119b15c737 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -34,6 +34,7 @@ class Key < ActiveRecord::Base value&.delete!("\n\r") value.strip! unless value.blank? write_attribute(:key, value) + @public_key = nil end def publishable_key diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 8d9a30397a9..0ba00d447e8 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -524,6 +524,14 @@ class MergeRequest < ActiveRecord::Base true end + def ff_merge_possible? + project.repository.ancestor?(target_branch_sha, diff_head_sha) + end + + def should_be_rebased? + project.ff_merge_must_be_possible? && !ff_merge_possible? + end + def can_cancel_merge_when_pipeline_succeeds?(current_user) can_be_merged_by?(current_user) || self.author == current_user end @@ -552,14 +560,20 @@ class MergeRequest < ActiveRecord::Base commits_for_notes_limit = 100 commit_ids = commit_shas.take(commits_for_notes_limit) - Note.where( - "(project_id = :target_project_id AND noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR" + - "((project_id = :source_project_id OR project_id = :target_project_id) AND noteable_type = 'Commit' AND commit_id IN (:commit_ids))", - mr_id: id, - commit_ids: commit_ids, - target_project_id: target_project_id, - source_project_id: source_project_id - ) + commit_notes = Note + .except(:order) + .where(project_id: [source_project_id, target_project_id]) + .where(noteable_type: 'Commit', commit_id: commit_ids) + + # We're using a UNION ALL here since this results in better performance + # compared to using OR statements. We're using UNION ALL since the queries + # used won't produce any duplicates (e.g. a note for a commit can't also be + # a note for an MR). + union = Gitlab::SQL::Union + .new([notes, commit_notes], remove_duplicates: false) + .to_sql + + Note.from("(#{union}) #{Note.table_name}") end alias_method :discussion_notes, :related_notes @@ -734,10 +748,9 @@ class MergeRequest < ActiveRecord::Base end def has_ci? - has_ci_integration = source_project.try(:ci_service) - uses_gitlab_ci = all_pipelines.any? + return false if has_no_commits? - (has_ci_integration || uses_gitlab_ci) && commits.any? + !!(head_pipeline_id || all_pipelines.any? || source_project&.ci_service) end def branch_missing? diff --git a/app/models/personal_access_token.rb b/app/models/personal_access_token.rb index 1f9d712ef84..cfcb03138b7 100644 --- a/app/models/personal_access_token.rb +++ b/app/models/personal_access_token.rb @@ -17,6 +17,8 @@ class PersonalAccessToken < ActiveRecord::Base validates :scopes, presence: true validate :validate_scopes + after_initialize :set_default_scopes, if: :persisted? + def revoke! update!(revoked: true) end @@ -32,4 +34,8 @@ class PersonalAccessToken < ActiveRecord::Base errors.add :scopes, "can only contain available scopes" end end + + def set_default_scopes + self.scopes = Gitlab::Auth::DEFAULT_SCOPES if self.scopes.empty? + end end diff --git a/app/models/project.rb b/app/models/project.rb index f7221e4f3b2..59b5a5b3cd7 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -64,6 +64,7 @@ class Project < ActiveRecord::Base # Storage specific hooks after_initialize :use_hashed_storage + after_create :check_repository_absence! after_create :ensure_storage_path_exists after_save :ensure_storage_path_exists, if: :namespace_id_changed? @@ -72,6 +73,7 @@ class Project < ActiveRecord::Base attr_accessor :old_path_with_namespace attr_accessor :template_name attr_writer :pipeline_status + attr_accessor :skip_disk_validation alias_attribute :title, :name @@ -227,7 +229,7 @@ class Project < ActiveRecord::Base validates :import_url, importable_url: true, if: [:external_import?, :import_url_changed?] validates :star_count, numericality: { greater_than_or_equal_to: 0 } validate :check_limit, on: :create - validate :can_create_repository?, on: [:create, :update], if: ->(project) { !project.persisted? || project.renamed? } + validate :check_repository_path_availability, on: :update, if: ->(project) { project.renamed? } validate :avatar_type, if: ->(project) { project.avatar.present? && project.avatar_changed? } validates :avatar, file_size: { maximum: 200.kilobytes.to_i } @@ -245,6 +247,9 @@ class Project < ActiveRecord::Base scope :pending_delete, -> { where(pending_delete: true) } scope :without_deleted, -> { where(pending_delete: false) } + scope :with_hashed_storage, -> { where('storage_version >= 1') } + scope :with_legacy_storage, -> { where(storage_version: [nil, 0]) } + scope :sorted_by_activity, -> { reorder(last_activity_at: :desc) } scope :sorted_by_stars, -> { reorder('projects.star_count DESC') } @@ -1015,12 +1020,15 @@ class Project < ActiveRecord::Base end # Check if repository already exists on disk - def can_create_repository? + def check_repository_path_availability + return true if skip_disk_validation return false unless repository_storage_path expires_full_path_cache # we need to clear cache to validate renames correctly - if gitlab_shell.exists?(repository_storage_path, "#{disk_path}.git") + # Check if repository with same path already exists on disk we can + # skip this for the hashed storage because the path does not change + if legacy_storage? && repository_with_same_path_already_exists? errors.add(:base, 'There is already a repository with that name on disk') return false end @@ -1032,7 +1040,7 @@ class Project < ActiveRecord::Base # Forked import is handled asynchronously return if forked? && !force - if gitlab_shell.add_repository(repository_storage_path, disk_path) + if gitlab_shell.add_repository(repository_storage, disk_path) repository.after_create true else @@ -1550,18 +1558,72 @@ class Project < ActiveRecord::Base end def legacy_storage? - self.storage_version.nil? + [nil, 0].include?(self.storage_version) + end + + def hashed_storage? + self.storage_version && self.storage_version >= 1 end def renamed? persisted? && path_changed? end + def merge_method + if self.merge_requests_ff_only_enabled + :ff + elsif self.merge_requests_rebase_enabled + :rebase_merge + else + :merge + end + end + + def merge_method=(method) + case method.to_s + when "ff" + self.merge_requests_ff_only_enabled = true + self.merge_requests_rebase_enabled = true + when "rebase_merge" + self.merge_requests_ff_only_enabled = false + self.merge_requests_rebase_enabled = true + when "merge" + self.merge_requests_ff_only_enabled = false + self.merge_requests_rebase_enabled = false + end + end + + def ff_merge_must_be_possible? + self.merge_requests_ff_only_enabled || self.merge_requests_rebase_enabled + end + + def migrate_to_hashed_storage! + return if hashed_storage? + + update!(repository_read_only: true) + + if repo_reference_count > 0 || wiki_reference_count > 0 + ProjectMigrateHashedStorageWorker.perform_in(Gitlab::ReferenceCounter::REFERENCE_EXPIRE_TIME, id) + else + ProjectMigrateHashedStorageWorker.perform_async(id) + end + end + + def storage_version=(value) + super + + @storage = nil if storage_version_changed? + end + + def gl_repository(is_wiki:) + Gitlab::GlRepository.gl_repository(self, is_wiki) + end + private def storage @storage ||= - if self.storage_version && self.storage_version >= 1 + if hashed_storage? Storage::HashedProject.new(self) else Storage::LegacyProject.new(self) @@ -1574,6 +1636,27 @@ class Project < ActiveRecord::Base end end + def repo_reference_count + Gitlab::ReferenceCounter.new(gl_repository(is_wiki: false)).value + end + + def wiki_reference_count + Gitlab::ReferenceCounter.new(gl_repository(is_wiki: true)).value + end + + def check_repository_absence! + return if skip_disk_validation + + if repository_storage_path.blank? || repository_with_same_path_already_exists? + errors.add(:base, 'There is already a repository with that name on disk') + throw :abort + end + end + + def repository_with_same_path_already_exists? + gitlab_shell.exists?(repository_storage_path, "#{disk_path}.git") + end + # set last_activity_at to the same as created_at def set_last_activity_at update_column(:last_activity_at, self.created_at) diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb index 698fdf7a20c..bb7be29ef66 100644 --- a/app/models/project_wiki.rb +++ b/app/models/project_wiki.rb @@ -54,12 +54,15 @@ class ProjectWiki [Gitlab.config.gitlab.relative_url_root, '/', @project.full_path, '/wikis'].join('') end - # Returns the Gollum::Wiki object. + # Returns the Gitlab::Git::Wiki object. def wiki @wiki ||= begin - Gollum::Wiki.new(path_to_repo) - rescue Rugged::OSError - create_repo! + gl_repository = Gitlab::GlRepository.gl_repository(project, true) + raw_repository = Gitlab::Git::Repository.new(project.repository_storage, disk_path + '.git', gl_repository) + + create_repo!(raw_repository) unless raw_repository.exists? + + Gitlab::Git::Wiki.new(raw_repository) end end @@ -86,20 +89,14 @@ class ProjectWiki # Returns an initialized WikiPage instance or nil def find_page(title, version = nil) page_title, page_dir = page_title_and_dir(title) - if page = wiki.page(page_title, version, page_dir) + + if page = wiki.page(title: page_title, version: version, dir: page_dir) WikiPage.new(self, page, true) - else - nil end end - def find_file(name, version = nil, try_on_disk = true) - version = wiki.ref if version.nil? # Gollum::Wiki#file ? - if wiki_file = wiki.file(name, version, try_on_disk) - wiki_file - else - nil - end + def find_file(name, version = nil) + wiki.file(name, version) end def create_page(title, content, format = :markdown, message = nil) @@ -108,7 +105,7 @@ class ProjectWiki wiki.write_page(title, format.to_sym, content, commit) update_project_activity - rescue Gollum::DuplicatePageError => e + rescue Gitlab::Git::Wiki::DuplicatePageError => e @error_message = "Duplicate page: #{e.message}" return false end @@ -116,13 +113,13 @@ class ProjectWiki def update_page(page, content:, title: nil, format: :markdown, message: nil) commit = commit_details(:updated, message, page.title) - wiki.update_page(page, title || page.name, format.to_sym, content, commit) + wiki.update_page(page.path, title || page.name, format.to_sym, content, commit) update_project_activity end def delete_page(page, message = nil) - wiki.delete_page(page, commit_details(:deleted, message, page.title)) + wiki.delete_page(page.path, commit_details(:deleted, message, page.title)) update_project_activity end @@ -145,20 +142,8 @@ class ProjectWiki wiki.class.default_ref end - def create_repo! - if init_repo(disk_path) - wiki = Gollum::Wiki.new(path_to_repo) - else - raise CouldNotCreateWikiError - end - - repository.after_create - - wiki - end - def ensure_repository - create_repo! unless repository_exists? + raise CouldNotCreateWikiError unless wiki.repository_exists? end def hook_attrs @@ -173,24 +158,24 @@ class ProjectWiki private - def init_repo(disk_path) - gitlab_shell.add_repository(project.repository_storage_path, disk_path) + def create_repo!(raw_repository) + gitlab_shell.add_repository(project.repository_storage, disk_path) + + raise CouldNotCreateWikiError unless raw_repository.exists? + + repository.after_create end def commit_details(action, message = nil, title = nil) commit_message = message || default_message(action, title) - { email: @user.email, name: @user.name, message: commit_message } + Gitlab::Git::Wiki::CommitDetails.new(@user.name, @user.email, commit_message) end def default_message(action, title) "#{@user.username} #{action} page: #{title}" end - def path_to_repo - @path_to_repo ||= File.join(project.repository_storage_path, "#{disk_path}.git") - end - def update_project_activity @project.touch(:last_activity_at, :last_repository_updated_at) end diff --git a/app/models/repository.rb b/app/models/repository.rb index 90cede9d3d4..d725c65081d 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -34,7 +34,10 @@ class Repository CACHED_METHODS = %i(size commit_count rendered_readme contribution_guide changelog license_blob license_key gitignore koding_yml gitlab_ci_yml branch_names tag_names branch_count - tag_count avatar exists? empty? root_ref).freeze + tag_count avatar exists? empty? root_ref has_visible_content?).freeze + + # Methods that use cache_method but only memoize the value + MEMOIZED_CACHED_METHODS = %i(license empty_repo?).freeze # Certain method caches should be refreshed when certain types of files are # changed. This Hash maps file types (as returned by Gitlab::FileDetector) to @@ -91,12 +94,6 @@ class Repository ) end - # we need to have this method here because it is not cached in ::Git and - # the method is called multiple times for every request - def has_visible_content? - branch_count > 0 - end - def inspect "#<#{self.class.name}:#{@disk_path}>" end @@ -275,7 +272,7 @@ class Repository end def expire_branches_cache - expire_method_caches(%i(branch_names branch_count)) + expire_method_caches(%i(branch_names branch_count has_visible_content?)) @local_branches = nil @branch_exists_memo = nil end @@ -346,7 +343,7 @@ class Repository def expire_emptiness_caches return unless empty? - expire_method_caches(%i(empty?)) + expire_method_caches(%i(empty? has_visible_content?)) end def lookup_cache @@ -489,13 +486,7 @@ class Repository def exists? return false unless full_path - Gitlab::GitalyClient.migrate(:repository_exists) do |enabled| - if enabled - raw_repository.exists? - else - refs_directory_exists? - end - end + raw_repository.exists? end cache_method :exists? @@ -529,13 +520,17 @@ class Repository delegate :tag_names, to: :raw_repository cache_method :tag_names, fallback: [] - delegate :branch_count, :tag_count, to: :raw_repository + delegate :branch_count, :tag_count, :has_visible_content?, to: :raw_repository cache_method :branch_count, fallback: 0 cache_method :tag_count, fallback: 0 + cache_method :has_visible_content?, fallback: false def avatar - if tree = file_on_head(:avatar) - tree.path + # n+1: https://gitlab.com/gitlab-org/gitlab-ce/issues/38327 + Gitlab::GitalyClient.allow_n_plus_1_calls do + if tree = file_on_head(:avatar) + tree.path + end end end cache_method :avatar @@ -855,6 +850,25 @@ class Repository end end + def ff_merge(user, source, target_branch, merge_request: nil) + our_commit = rugged.branches[target_branch].target + their_commit = + if source.is_a?(Gitlab::Git::Commit) + source.raw_commit + else + rugged.lookup(source) + end + + raise 'Invalid merge target' if our_commit.nil? + raise 'Invalid merge source' if their_commit.nil? + + with_branch(user, target_branch) do |start_commit| + merge_request&.update(in_progress_merge_commit_sha: their_commit.oid) + + their_commit.oid + end + end + def revert( user, commit, branch_name, message, start_branch_name: nil, start_project: project) @@ -975,7 +989,7 @@ class Repository end def create_ref(ref, ref_path) - fetch_ref(path_to_repo, ref, ref_path) + raw_repository.write_ref(ref_path, ref) end def ls_files(ref) @@ -1060,12 +1074,6 @@ class Repository blob.data end - def refs_directory_exists? - circuit_breaker.perform do - File.exist?(File.join(path_to_repo, 'refs')) - end - end - def cache # TODO: should we use UUIDs here? We could move repositories without clearing this cache @cache ||= RepositoryCache.new(full_path, @project.id) @@ -1117,10 +1125,6 @@ class Repository Gitlab::Git::Repository.new(project.repository_storage, disk_path + '.git', Gitlab::GlRepository.gl_repository(project, false)) end - def circuit_breaker - @circuit_breaker ||= Gitlab::Git::Storage::CircuitBreaker.for_storage(project.repository_storage) - end - def find_commits_by_message_by_shelling_out(query, ref, path, limit, offset) ref ||= root_ref diff --git a/app/models/storage/hashed_project.rb b/app/models/storage/hashed_project.rb index fae1b64961a..f025f40994e 100644 --- a/app/models/storage/hashed_project.rb +++ b/app/models/storage/hashed_project.rb @@ -4,6 +4,7 @@ module Storage delegate :gitlab_shell, :repository_storage_path, to: :project ROOT_PATH_PREFIX = '@hashed'.freeze + STORAGE_VERSION = 1 def initialize(project) @project = project diff --git a/app/models/user.rb b/app/models/user.rb index 7a9561a04ff..4ba9130a75a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -60,7 +60,7 @@ class User < ActiveRecord::Base lease = Gitlab::ExclusiveLease.new("user_update_tracked_fields:#{id}", timeout: 1.hour.to_i) return unless lease.try_obtain - Users::UpdateService.new(self).execute(validate: false) + Users::UpdateService.new(self, user: self).execute(validate: false) end attr_accessor :force_random_password @@ -130,6 +130,8 @@ class User < ActiveRecord::Base has_many :assigned_issues, class_name: "Issue", through: :issue_assignees, source: :issue has_many :assigned_merge_requests, dependent: :nullify, foreign_key: :assignee_id, class_name: "MergeRequest" # rubocop:disable Cop/ActiveRecordDependent + has_many :custom_attributes, class_name: 'UserCustomAttribute' + # # Validations # @@ -537,11 +539,11 @@ class User < ActiveRecord::Base def update_emails_with_primary_email previous_email = previous_changes[:email][0] # grab this before the DestroyService is called primary_email_record = emails.find_by(email: email) - Emails::DestroyService.new(self).execute(primary_email_record) if primary_email_record + Emails::DestroyService.new(self, user: self).execute(primary_email_record) if primary_email_record # the original primary email was confirmed, and we want that to carry over. We don't # have access to the original confirmation values at this point, so just set confirmed_at - Emails::CreateService.new(self, email: previous_email).execute(confirmed_at: confirmed_at) + Emails::CreateService.new(self, user: self, email: previous_email).execute(confirmed_at: confirmed_at) end def update_invalid_gpg_signatures @@ -703,7 +705,11 @@ class User < ActiveRecord::Base end def ldap_user? - identities.exists?(["provider LIKE ? AND extern_uid IS NOT NULL", "ldap%"]) + if identities.loaded? + identities.find { |identity| identity.provider.start_with?('ldap') && !identity.extern_uid.nil? } + else + identities.exists?(["provider LIKE ? AND extern_uid IS NOT NULL", "ldap%"]) + end end def ldap_identity @@ -1029,7 +1035,7 @@ class User < ActiveRecord::Base if attempts_exceeded? lock_access! unless access_locked? else - Users::UpdateService.new(self).execute(validate: false) + Users::UpdateService.new(self, user: self).execute(validate: false) end end @@ -1086,6 +1092,12 @@ class User < ActiveRecord::Base user_synced_attributes_metadata&.read_only?(attribute) end + # override, from Devise + def lock_access! + Gitlab::AppLogger.info("Account Locked: username=#{username}") + super + end + protected # override, from Devise::Validatable @@ -1211,7 +1223,7 @@ class User < ActiveRecord::Base &creation_block ) - Users::UpdateService.new(user).execute(validate: false) + Users::UpdateService.new(user, user: user).execute(validate: false) user ensure Gitlab::ExclusiveLease.cancel(lease_key, uuid) diff --git a/app/models/user_custom_attribute.rb b/app/models/user_custom_attribute.rb new file mode 100644 index 00000000000..eff25b31f9b --- /dev/null +++ b/app/models/user_custom_attribute.rb @@ -0,0 +1,6 @@ +class UserCustomAttribute < ActiveRecord::Base + belongs_to :user + + validates :user_id, :key, :value, presence: true + validates :key, uniqueness: { scope: [:user_id] } +end diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb index f2315bb3dbb..5f710961f95 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -50,7 +50,7 @@ class WikiPage # The Gitlab ProjectWiki instance. attr_reader :wiki - # The raw Gollum::Page instance. + # The raw Gitlab::Git::WikiPage instance. attr_reader :page # The attributes Hash used for storing and validating @@ -75,7 +75,7 @@ class WikiPage if @attributes[:slug].present? @attributes[:slug] else - wiki.wiki.preview_page(title, '', format).url_path + wiki.wiki.preview_slug(title, format) end end @@ -131,7 +131,7 @@ class WikiPage def versions return [] unless persisted? - @page.versions + wiki.wiki.page_versions(@page.path) end def commit @@ -264,8 +264,8 @@ class WikiPage end page_title, page_dir = wiki.page_title_and_dir(page_details) - gollum_wiki = wiki.wiki - @page = gollum_wiki.paged(page_title, page_dir) + gitlab_git_wiki = wiki.wiki + @page = gitlab_git_wiki.page(title: page_title, dir: page_dir) set_attributes @persisted = errors.blank? diff --git a/app/policies/global_policy.rb b/app/policies/global_policy.rb index 1be7bbe9953..64e550d19d0 100644 --- a/app/policies/global_policy.rb +++ b/app/policies/global_policy.rb @@ -11,6 +11,8 @@ class GlobalPolicy < BasePolicy with_options scope: :user, score: 0 condition(:access_locked) { @user.access_locked? } + condition(:can_create_fork, scope: :user) { @user.manageable_namespaces.any? { |namespace| @user.can?(:create_projects, namespace) } } + rule { anonymous }.policy do prevent :log_in prevent :access_api @@ -40,6 +42,10 @@ class GlobalPolicy < BasePolicy enable :create_group end + rule { can_create_fork }.policy do + enable :create_fork + end + rule { access_locked }.policy do prevent :log_in end @@ -47,4 +53,9 @@ class GlobalPolicy < BasePolicy rule { ~(anonymous & restricted_public_level) }.policy do enable :read_users_list end + + rule { admin }.policy do + enable :read_custom_attribute + enable :update_custom_attribute + end end diff --git a/app/policies/namespace_policy.rb b/app/policies/namespace_policy.rb index 85b67f0a237..92213f0155e 100644 --- a/app/policies/namespace_policy.rb +++ b/app/policies/namespace_policy.rb @@ -1,10 +1,14 @@ class NamespacePolicy < BasePolicy rule { anonymous }.prevent_all + condition(:personal_project, scope: :subject) { @subject.kind == 'user' } + condition(:can_create_personal_project, scope: :user) { @user.can_create_project? } condition(:owner) { @subject.owner == @user } rule { owner | admin }.policy do enable :create_projects enable :admin_namespace end + + rule { personal_project & ~can_create_personal_project }.prevent :create_projects end diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb index 2df84e58575..a25882cbb62 100644 --- a/app/presenters/merge_request_presenter.rb +++ b/app/presenters/merge_request_presenter.rb @@ -31,7 +31,7 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated end def remove_wip_path - if can?(current_user, :update_merge_request, merge_request.project) + if work_in_progress? && can?(current_user, :update_merge_request, merge_request.project) remove_wip_project_merge_request_path(project, merge_request) end end diff --git a/app/serializers/commit_entity.rb b/app/serializers/commit_entity.rb index e4e9d8ef90a..c8dd98cc04d 100644 --- a/app/serializers/commit_entity.rb +++ b/app/serializers/commit_entity.rb @@ -1,4 +1,4 @@ -class CommitEntity < API::Entities::RepoCommit +class CommitEntity < API::Entities::Commit include RequestAwareEntity expose :author, using: UserEntity diff --git a/app/serializers/container_repositories_serializer.rb b/app/serializers/container_repositories_serializer.rb new file mode 100644 index 00000000000..56dc70b5687 --- /dev/null +++ b/app/serializers/container_repositories_serializer.rb @@ -0,0 +1,3 @@ +class ContainerRepositoriesSerializer < BaseSerializer + entity ContainerRepositoryEntity +end diff --git a/app/serializers/container_repository_entity.rb b/app/serializers/container_repository_entity.rb new file mode 100644 index 00000000000..1103cf30a07 --- /dev/null +++ b/app/serializers/container_repository_entity.rb @@ -0,0 +1,25 @@ +class ContainerRepositoryEntity < Grape::Entity + include RequestAwareEntity + + expose :id, :path, :location + + expose :tags_path do |repository| + project_registry_repository_tags_path(project, repository, format: :json) + end + + expose :destroy_path, if: -> (*) { can_destroy? } do |repository| + project_container_registry_path(project, repository, format: :json) + end + + private + + alias_method :repository, :object + + def project + request.project + end + + def can_destroy? + can?(request.current_user, :update_container_image, project) + end +end diff --git a/app/serializers/container_tag_entity.rb b/app/serializers/container_tag_entity.rb new file mode 100644 index 00000000000..ec1fc349586 --- /dev/null +++ b/app/serializers/container_tag_entity.rb @@ -0,0 +1,23 @@ +class ContainerTagEntity < Grape::Entity + include RequestAwareEntity + + expose :name, :location, :revision, :total_size, :created_at + + expose :destroy_path, if: -> (*) { can_destroy? } do |tag| + project_registry_repository_tag_path(project, tag.repository, tag.name, format: :json) + end + + private + + alias_method :tag, :object + + def project + request.project + end + + def can_destroy? + # TODO: We check permission against @project, not tag, + # as tag is no AR object that is attached to project + can?(request.current_user, :update_container_image, project) + end +end diff --git a/app/serializers/container_tags_serializer.rb b/app/serializers/container_tags_serializer.rb new file mode 100644 index 00000000000..6ff3adff135 --- /dev/null +++ b/app/serializers/container_tags_serializer.rb @@ -0,0 +1,17 @@ +class ContainerTagsSerializer < BaseSerializer + entity ContainerTagEntity + + def with_pagination(request, response) + tap { @paginator = Gitlab::Serializer::Pagination.new(request, response) } + end + + def paginated? + @paginator.present? + end + + def represent(resource, opts = {}) + resource = @paginator.paginate(resource) if paginated? + + super(resource, opts) + end +end diff --git a/app/serializers/merge_request_entity.rb b/app/serializers/merge_request_entity.rb index 07650ce6f20..36537c5bd02 100644 --- a/app/serializers/merge_request_entity.rb +++ b/app/serializers/merge_request_entity.rb @@ -13,12 +13,16 @@ class MergeRequestEntity < IssuableEntity expose :target_branch expose :target_project_id + expose :should_be_rebased?, as: :should_be_rebased + expose :ff_only_enabled do |merge_request| + merge_request.project.merge_requests_ff_only_enabled + end + # Events expose :merge_event, using: EventEntity expose :closed_event, using: EventEntity # User entities - expose :author, using: UserEntity expose :merge_user, using: UserEntity # Diff sha's @@ -26,7 +30,6 @@ class MergeRequestEntity < IssuableEntity merge_request.diff_head_sha if merge_request.diff_head_commit end - expose :merge_commit_sha expose :merge_commit_message expose :head_pipeline, with: PipelineDetailsEntity, as: :pipeline diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb index d20de9b16a4..31a712ccc1b 100644 --- a/app/services/ci/create_pipeline_service.rb +++ b/app/services/ci/create_pipeline_service.rb @@ -2,110 +2,55 @@ module Ci class CreatePipelineService < BaseService attr_reader :pipeline - def execute(source, ignore_skip_ci: false, save_on_errors: true, trigger_request: nil, schedule: nil) + SEQUENCE = [Gitlab::Ci::Pipeline::Chain::Validate::Abilities, + Gitlab::Ci::Pipeline::Chain::Validate::Repository, + Gitlab::Ci::Pipeline::Chain::Validate::Config, + Gitlab::Ci::Pipeline::Chain::Skip, + Gitlab::Ci::Pipeline::Chain::Create].freeze + + def execute(source, ignore_skip_ci: false, save_on_errors: true, trigger_request: nil, schedule: nil, &block) @pipeline = Ci::Pipeline.new( source: source, project: project, ref: ref, sha: sha, before_sha: before_sha, - tag: tag?, + tag: tag_exists?, trigger_requests: Array(trigger_request), user: current_user, pipeline_schedule: schedule, protected: project.protected_for?(ref) ) - result = validate_project_and_git_items || - validate_pipeline(ignore_skip_ci: ignore_skip_ci, - save_on_errors: save_on_errors) + command = OpenStruct.new(ignore_skip_ci: ignore_skip_ci, + save_incompleted: save_on_errors, + seeds_block: block, + project: project, + current_user: current_user) - return result if result + sequence = Gitlab::Ci::Pipeline::Chain::Sequence + .new(pipeline, command, SEQUENCE) - begin - Ci::Pipeline.transaction do - pipeline.save! + sequence.build! do |pipeline, sequence| + update_merge_requests_head_pipeline if pipeline.persisted? - yield(pipeline) if block_given? + if sequence.complete? + cancel_pending_pipelines if project.auto_cancel_pending_pipelines? + pipeline_created_counter.increment(source: source) - Ci::CreatePipelineStagesService - .new(project, current_user) - .execute(pipeline) + pipeline.process! end - rescue ActiveRecord::RecordInvalid => e - return error("Failed to persist the pipeline: #{e}") end - - update_merge_requests_head_pipeline - - cancel_pending_pipelines if project.auto_cancel_pending_pipelines? - - pipeline_created_counter.increment(source: source) - - pipeline.tap(&:process!) end private - def validate_project_and_git_items - unless project.builds_enabled? - return error('Pipeline is disabled') - end - - unless allowed_to_trigger_pipeline? - if can?(current_user, :create_pipeline, project) - return error("Insufficient permissions for protected ref '#{ref}'") - else - return error('Insufficient permissions to create a new pipeline') - end - end - - unless branch? || tag? - return error('Reference not found') - end - - unless commit - return error('Commit not found') - end - end - - def validate_pipeline(ignore_skip_ci:, save_on_errors:) - unless pipeline.config_processor - unless pipeline.ci_yaml_file - return error("Missing #{pipeline.ci_yaml_file_path} file") - end - return error(pipeline.yaml_errors, save: save_on_errors) - end - - if !ignore_skip_ci && skip_ci? - pipeline.skip if save_on_errors - return pipeline - end - - unless pipeline.has_stage_seeds? - return error('No stages / jobs for this pipeline.') - end - end - - def allowed_to_trigger_pipeline? - if current_user - allowed_to_create? - else # legacy triggers don't have a corresponding user - !project.protected_for?(ref) - end + def commit + @commit ||= project.commit(origin_sha || origin_ref) end - def allowed_to_create? - return unless can?(current_user, :create_pipeline, project) - - access = Gitlab::UserAccess.new(current_user, project: project) - if branch? - access.can_update_branch?(ref) - elsif tag? - access.can_create_tag?(ref) - else - true # Allow it for now and we'll reject when we check ref existence - end + def sha + commit.try(:id) end def update_merge_requests_head_pipeline @@ -115,11 +60,6 @@ module Ci .update_all(head_pipeline_id: @pipeline.id) end - def skip_ci? - return false unless pipeline.git_commit_message - pipeline.git_commit_message =~ /\[(ci[ _-]skip|skip[ _-]ci)\]/i - end - def cancel_pending_pipelines Gitlab::OptimisticLocking.retry_lock(auto_cancelable_pipelines) do |cancelables| cancelables.find_each do |cancelable| @@ -136,14 +76,6 @@ module Ci .created_or_pending end - def commit - @commit ||= project.commit(origin_sha || origin_ref) - end - - def sha - commit.try(:id) - end - def before_sha params[:checkout_sha] || params[:before] || Gitlab::Git::BLANK_SHA end @@ -156,41 +88,17 @@ module Ci params[:ref] end - def branch? - return @is_branch if defined?(@is_branch) - - @is_branch = - project.repository.ref_exists?(Gitlab::Git::BRANCH_REF_PREFIX + ref) - end - - def tag? - return @is_tag if defined?(@is_tag) - - @is_tag = - project.repository.ref_exists?(Gitlab::Git::TAG_REF_PREFIX + ref) + def tag_exists? + project.repository.tag_exists?(ref) end def ref @ref ||= Gitlab::Git.ref_name(origin_ref) end - def valid_sha? - origin_sha && origin_sha != Gitlab::Git::BLANK_SHA - end - - def error(message, save: false) - pipeline.tap do - pipeline.errors.add(:base, message) - - if save - pipeline.drop - update_merge_requests_head_pipeline - end - end - end - def pipeline_created_counter - @pipeline_created_counter ||= Gitlab::Metrics.counter(:pipelines_created_total, "Counter of pipelines created") + @pipeline_created_counter ||= Gitlab::Metrics + .counter(:pipelines_created_total, "Counter of pipelines created") end end end diff --git a/app/services/emails/base_service.rb b/app/services/emails/base_service.rb index caddbf505fe..5bbceeb3b3f 100644 --- a/app/services/emails/base_service.rb +++ b/app/services/emails/base_service.rb @@ -1,7 +1,8 @@ module Emails class BaseService - def initialize(user, params = {}) - @user, @params = user, params.dup + def initialize(current_user, params = {}) + @current_user, @params = current_user, params.dup + @user = params.delete(:user) end end end diff --git a/app/services/emails/destroy_service.rb b/app/services/emails/destroy_service.rb index aef863bd9d1..1ed131fe326 100644 --- a/app/services/emails/destroy_service.rb +++ b/app/services/emails/destroy_service.rb @@ -7,7 +7,7 @@ module Emails private def update_secondary_emails! - result = ::Users::UpdateService.new(@user).execute do |user| + result = ::Users::UpdateService.new(@current_user, user: @user).execute do |user| user.update_secondary_emails! end diff --git a/app/services/merge_requests/ff_merge_service.rb b/app/services/merge_requests/ff_merge_service.rb new file mode 100644 index 00000000000..ba6853b835a --- /dev/null +++ b/app/services/merge_requests/ff_merge_service.rb @@ -0,0 +1,24 @@ +module MergeRequests + # MergeService class + # + # Do git fast-forward merge and in case of success + # mark merge request as merged and execute all hooks and notifications + # Executed when you do fast-forward merge via GitLab UI + # + class FfMergeService < MergeRequests::MergeService + private + + def commit + repository.ff_merge(current_user, + source, + merge_request.target_branch, + merge_request: merge_request) + rescue Gitlab::Git::HooksService::PreReceiveError => e + raise MergeError, e.message + rescue StandardError => e + raise MergeError, "Something went wrong during merge: #{e.message}" + ensure + merge_request.update(in_progress_merge_commit_sha: nil) + end + end +end diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb index 07cbd8f92a9..a110abf8256 100644 --- a/app/services/merge_requests/merge_service.rb +++ b/app/services/merge_requests/merge_service.rb @@ -11,16 +11,21 @@ module MergeRequests attr_reader :merge_request, :source def execute(merge_request) + if project.merge_requests_ff_only_enabled && !self.is_a?(FfMergeService) + FfMergeService.new(project, current_user, params).execute(merge_request) + return + end + @merge_request = merge_request unless @merge_request.mergeable? - return log_merge_error('Merge request is not mergeable', save_message_on_model: true) + return handle_merge_error(log_message: 'Merge request is not mergeable', save_message_on_model: true) end @source = find_merge_source unless @source - return log_merge_error('No source for merge', save_message_on_model: true) + return handle_merge_error(log_message: 'No source for merge', save_message_on_model: true) end merge_request.in_locked_state do @@ -31,8 +36,7 @@ module MergeRequests end end rescue MergeError => e - clean_merge_jid - log_merge_error(e.message, save_message_on_model: true) + handle_merge_error(log_message: e.message, save_message_on_model: true) end private @@ -74,10 +78,16 @@ module MergeRequests @merge_request.force_remove_source_branch? ? @merge_request.author : current_user end - def log_merge_error(message, save_message_on_model: false) - Rails.logger.error("MergeService ERROR: #{merge_request_info} - #{message}") + # Logs merge error message and cleans `MergeRequest#merge_jid`. + # + def handle_merge_error(log_message:, save_message_on_model: false) + Rails.logger.error("MergeService ERROR: #{merge_request_info} - #{log_message}") - @merge_request.update(merge_error: message) if save_message_on_model + if save_message_on_model + @merge_request.update(merge_error: log_message, merge_jid: nil) + else + clean_merge_jid + end end def merge_request_info diff --git a/app/services/merge_requests/post_merge_service.rb b/app/services/merge_requests/post_merge_service.rb index 261a8bfa200..b1d6bac4d4a 100644 --- a/app/services/merge_requests/post_merge_service.rb +++ b/app/services/merge_requests/post_merge_service.rb @@ -14,6 +14,7 @@ module MergeRequests notification_service.merge_mr(merge_request, current_user) execute_hooks(merge_request, 'merge') invalidate_cache_counts(merge_request, users: merge_request.assignees) + merge_request.update_project_counter_caches end private diff --git a/app/services/projects/hashed_storage_migration_service.rb b/app/services/projects/hashed_storage_migration_service.rb new file mode 100644 index 00000000000..41259de3a16 --- /dev/null +++ b/app/services/projects/hashed_storage_migration_service.rb @@ -0,0 +1,68 @@ +module Projects + class HashedStorageMigrationService < BaseService + include Gitlab::ShellAdapter + + attr_reader :old_disk_path, :new_disk_path + + def initialize(project, logger = nil) + @project = project + @logger ||= Rails.logger + end + + def execute + return if project.hashed_storage? + + @old_disk_path = project.disk_path + has_wiki = project.wiki.repository_exists? + + project.storage_version = Storage::HashedProject::STORAGE_VERSION + project.ensure_storage_path_exists + + @new_disk_path = project.disk_path + + result = move_repository(@old_disk_path, @new_disk_path) + + if has_wiki + result &&= move_repository("#{@old_disk_path}.wiki", "#{@new_disk_path}.wiki") + end + + unless result + rollback_folder_move + return + end + + project.repository_read_only = false + project.save! + + block_given? ? yield : result + end + + private + + def move_repository(from_name, to_name) + from_exists = gitlab_shell.exists?(project.repository_storage_path, "#{from_name}.git") + to_exists = gitlab_shell.exists?(project.repository_storage_path, "#{to_name}.git") + + # If we don't find the repository on either original or target we should log that as it could be an issue if the + # project was not originally empty. + if !from_exists && !to_exists + logger.warn "Can't find a repository on either source or target paths for #{project.full_path} (ID=#{project.id}) ..." + return false + elsif !from_exists + # Repository have been moved already. + return true + end + + gitlab_shell.mv_repository(project.repository_storage_path, from_name, to_name) + end + + def rollback_folder_move + move_repository(@new_disk_path, @old_disk_path) + move_repository("#{@new_disk_path}.wiki", "#{@old_disk_path}.wiki") + end + + def logger + @logger + end + end +end diff --git a/app/services/tags/create_service.rb b/app/services/tags/create_service.rb index b3f4a72d6fe..cc76d0df3a1 100644 --- a/app/services/tags/create_service.rb +++ b/app/services/tags/create_service.rb @@ -11,7 +11,7 @@ module Tags begin new_tag = repository.add_tag(current_user, tag_name, target, message) - rescue Rugged::TagError + rescue Gitlab::Git::Repository::TagExistsError return error("Tag #{tag_name} already exists") rescue Gitlab::Git::HooksService::PreReceiveError => ex return error(ex.message) diff --git a/app/services/users/update_service.rb b/app/services/users/update_service.rb index 6188b8a4349..15ca1a55a5b 100644 --- a/app/services/users/update_service.rb +++ b/app/services/users/update_service.rb @@ -2,22 +2,21 @@ module Users class UpdateService < BaseService include NewUserNotifier - def initialize(user, params = {}) - @user = user + def initialize(current_user, params = {}) + @current_user = current_user + @user = params.delete(:user) @params = params.dup end def execute(validate: true, &block) yield(@user) if block_given? - assign_attributes(&block) - user_exists = @user.persisted? - if @user.save(validate: validate) - notify_new_user(@user, nil) unless user_exists + assign_attributes(&block) - success + if @user.save(validate: validate) + notify_success(user_exists) else error(@user.errors.full_messages.uniq.join('. ')) end @@ -33,6 +32,12 @@ module Users private + def notify_success(user_exists) + notify_new_user(@user, nil) unless user_exists + + success + end + def assign_attributes(&block) if @user.user_synced_attributes_metadata params.except!(*@user.user_synced_attributes_metadata.read_only_attributes) diff --git a/app/views/admin/background_jobs/show.html.haml b/app/views/admin/background_jobs/show.html.haml index e5842bd1ea0..3ef8f2a3acb 100644 --- a/app/views/admin/background_jobs/show.html.haml +++ b/app/views/admin/background_jobs/show.html.haml @@ -1,6 +1,5 @@ - @no_container = true - page_title "Background Jobs" -= render 'admin/monitoring/head' %div{ class: container_class } %h3.page-title Background Jobs diff --git a/app/views/admin/cohorts/index.html.haml b/app/views/admin/cohorts/index.html.haml index bff53da1d9a..5e9a8c083af 100644 --- a/app/views/admin/cohorts/index.html.haml +++ b/app/views/admin/cohorts/index.html.haml @@ -1,6 +1,5 @@ - breadcrumb_title "Cohorts" - @no_container = true -= render "admin/dashboard/head" %div{ class: container_class } - if @cohorts diff --git a/app/views/admin/conversational_development_index/show.html.haml b/app/views/admin/conversational_development_index/show.html.haml index 833d4c612f8..30dd87f0463 100644 --- a/app/views/admin/conversational_development_index/show.html.haml +++ b/app/views/admin/conversational_development_index/show.html.haml @@ -1,8 +1,6 @@ - @no_container = true - page_title 'ConvDev Index' -= render 'admin/monitoring/head' - .container - if show_callout?('convdev_intro_callout_dismissed') = render 'callout' diff --git a/app/views/admin/dashboard/_head.html.haml b/app/views/admin/dashboard/_head.html.haml deleted file mode 100644 index c2151710884..00000000000 --- a/app/views/admin/dashboard/_head.html.haml +++ /dev/null @@ -1,37 +0,0 @@ -= content_for :sub_nav do - .scrolling-tabs-container.sub-nav-scroll - = render 'shared/nav_scroll' - .nav-links.sub-nav.scrolling-tabs - %ul{ class: (container_class) } - = nav_link(controller: :dashboard, html_options: {class: 'home'}) do - = link_to admin_root_path, title: 'Overview' do - %span - Overview - = nav_link(controller: [:admin, :projects]) do - = link_to admin_projects_path, title: 'Projects' do - %span - Projects - = nav_link(controller: :users) do - = link_to admin_users_path, title: 'Users' do - %span - Users - = nav_link(controller: :groups) do - = link_to admin_groups_path, title: 'Groups' do - %span - Groups - = nav_link path: 'builds#index' do - = link_to admin_jobs_path, title: 'Jobs' do - %span - Jobs - = nav_link path: ['runners#index', 'runners#show'] do - = link_to admin_runners_path, title: 'Runners' do - %span - Runners - = nav_link path: 'cohorts#index' do - = link_to admin_cohorts_path, title: 'Cohorts' do - %span - Cohorts - = nav_link(controller: :conversational_development_index) do - = link_to admin_conversational_development_index_path, title: 'ConvDev Index' do - %span - ConvDev Index diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml index d212c7ca965..2f0143c7eff 100644 --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@ -1,6 +1,5 @@ - @no_container = true - breadcrumb_title "Dashboard" -= render "admin/dashboard/head" %div{ class: container_class } .admin-dashboard.prepend-top-default diff --git a/app/views/admin/groups/index.html.haml b/app/views/admin/groups/index.html.haml index e5f380c78e2..535251fef5e 100644 --- a/app/views/admin/groups/index.html.haml +++ b/app/views/admin/groups/index.html.haml @@ -1,6 +1,5 @@ - @no_container = true - page_title "Groups" -= render "admin/dashboard/head" %div{ class: container_class } .top-area diff --git a/app/views/admin/health_check/show.html.haml b/app/views/admin/health_check/show.html.haml index 517db50b97f..10a3bed0a4f 100644 --- a/app/views/admin/health_check/show.html.haml +++ b/app/views/admin/health_check/show.html.haml @@ -1,7 +1,6 @@ - @no_container = true - page_title _('Health Check') - no_errors = @errors.blank? && @failing_storage_statuses.blank? -= render 'admin/monitoring/head' %div{ class: container_class } %h3.page-title= page_title diff --git a/app/views/admin/jobs/index.html.haml b/app/views/admin/jobs/index.html.haml index aa6e9db3900..0310498ae54 100644 --- a/app/views/admin/jobs/index.html.haml +++ b/app/views/admin/jobs/index.html.haml @@ -1,6 +1,5 @@ - breadcrumb_title "Jobs" - @no_container = true -= render "admin/dashboard/head" %div{ class: container_class } diff --git a/app/views/admin/logs/show.html.haml b/app/views/admin/logs/show.html.haml index ee87f25a225..78757b6384f 100644 --- a/app/views/admin/logs/show.html.haml +++ b/app/views/admin/logs/show.html.haml @@ -1,6 +1,5 @@ - @no_container = true - page_title "Logs" -= render 'admin/monitoring/head' %div{ class: container_class } %ul.nav-links.log-tabs diff --git a/app/views/admin/monitoring/_head.html.haml b/app/views/admin/monitoring/_head.html.haml deleted file mode 100644 index b3530915068..00000000000 --- a/app/views/admin/monitoring/_head.html.haml +++ /dev/null @@ -1,25 +0,0 @@ -= content_for :sub_nav do - .scrolling-tabs-container.sub-nav-scroll - = render 'shared/nav_scroll' - .nav-links.sub-nav.scrolling-tabs - %ul{ class: (container_class) } - = nav_link(controller: :system_info) do - = link_to admin_system_info_path, title: 'System Info' do - %span - System Info - = nav_link(controller: :background_jobs) do - = link_to admin_background_jobs_path, title: 'Background Jobs' do - %span - Background Jobs - = nav_link(controller: :logs) do - = link_to admin_logs_path, title: 'Logs' do - %span - Logs - = nav_link(controller: :health_check) do - = link_to admin_health_check_path, title: 'Health Check' do - %span - Health Check - = nav_link(controller: :requests_profiles) do - = link_to admin_requests_profiles_path, title: 'Requests Profiles' do - %span - Requests Profiles diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml index 3301f55b8a8..3f202fbf4fe 100644 --- a/app/views/admin/projects/index.html.haml +++ b/app/views/admin/projects/index.html.haml @@ -2,7 +2,6 @@ - page_title "Projects" - params[:visibility_level] ||= [] -= render "admin/dashboard/head" %div{ class: container_class } .top-area diff --git a/app/views/admin/requests_profiles/index.html.haml b/app/views/admin/requests_profiles/index.html.haml index b7db18b2d32..cb02a750490 100644 --- a/app/views/admin/requests_profiles/index.html.haml +++ b/app/views/admin/requests_profiles/index.html.haml @@ -1,6 +1,5 @@ - @no_container = true - page_title 'Requests Profiles' -= render 'admin/monitoring/head' %div{ class: container_class } %h3.page-title diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml index 6793ce557c4..43cea1358cc 100644 --- a/app/views/admin/runners/index.html.haml +++ b/app/views/admin/runners/index.html.haml @@ -1,6 +1,5 @@ - breadcrumb_title "Runners" - @no_container = true -= render "admin/dashboard/head" %div{ class: container_class } .bs-callout diff --git a/app/views/admin/system_info/show.html.haml b/app/views/admin/system_info/show.html.haml index fd0281e4961..6bf979a937e 100644 --- a/app/views/admin/system_info/show.html.haml +++ b/app/views/admin/system_info/show.html.haml @@ -1,6 +1,5 @@ - @no_container = true - page_title "System Info" -= render 'admin/monitoring/head' %div{ class: container_class } .prepend-top-default diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml index 5516134d8a0..38ce1564eff 100644 --- a/app/views/admin/users/index.html.haml +++ b/app/views/admin/users/index.html.haml @@ -1,6 +1,5 @@ - @no_container = true - page_title "Users" -= render "admin/dashboard/head" %div{ class: container_class } .prepend-top-default diff --git a/app/views/dashboard/projects/_nav.html.haml b/app/views/dashboard/projects/_nav.html.haml new file mode 100644 index 00000000000..3701e1c0578 --- /dev/null +++ b/app/views/dashboard/projects/_nav.html.haml @@ -0,0 +1,6 @@ +.top-area + %ul.nav-links + = nav_link(html_options: { class: ("active" unless params[:personal].present?) }) do + = link_to s_('DashboardProjects|All'), dashboard_projects_path + = nav_link(html_options: { class: ("active" if params[:personal].present?) }) do + = link_to s_('DashboardProjects|Personal'), filter_projects_path(personal: true) diff --git a/app/views/dashboard/projects/index.html.haml b/app/views/dashboard/projects/index.html.haml index a4dc49d2120..57a4da353fe 100644 --- a/app/views/dashboard/projects/index.html.haml +++ b/app/views/dashboard/projects/index.html.haml @@ -10,8 +10,9 @@ = render "projects/last_push" %div{ class: container_class } - - if has_projects_or_name?(@projects, params) + - if show_projects?(@projects, params) = render 'dashboard/projects_head' + = render 'nav' = render 'projects' - else = render "zero_authorized_projects" diff --git a/app/views/devise/mailer/_confirmation_instructions_account.html.haml b/app/views/devise/mailer/_confirmation_instructions_account.html.haml index 3090fc0a2c0..65565b7b8a8 100644 --- a/app/views/devise/mailer/_confirmation_instructions_account.html.haml +++ b/app/views/devise/mailer/_confirmation_instructions_account.html.haml @@ -1,9 +1,10 @@ +- confirmation_link = confirmation_url(@resource, confirmation_token: @token) - if @resource.unconfirmed_email.present? #content = email_default_heading(@resource.unconfirmed_email) %p Click the link below to confirm your email address. #cta - = link_to 'Confirm your email address', confirmation_url(@resource, confirmation_token: @token) + = link_to 'Confirm your email address', confirmation_link - else #content - if Gitlab.com? @@ -12,4 +13,4 @@ = email_default_heading("Welcome, #{@resource.name}!") %p To get started, click the link below to confirm your account. #cta - = link_to 'Confirm your account', confirmation_url(@resource, confirmation_token: @token) + = link_to 'Confirm your account', confirmation_link diff --git a/app/views/groups/_head.html.haml b/app/views/groups/_head.html.haml deleted file mode 100644 index 0f63774fb9b..00000000000 --- a/app/views/groups/_head.html.haml +++ /dev/null @@ -1,17 +0,0 @@ -= content_for :sub_nav do - .scrolling-tabs-container.sub-nav-scroll - = render 'shared/nav_scroll' - .nav-links.sub-nav.scrolling-tabs - %ul{ class: container_class } - = nav_link(path: ['groups#show', 'groups#subgroups'], html_options: { class: 'home' }) do - = link_to group_path(@group), title: 'Group Home' do - %span - Home - - = nav_link(path: 'groups#activity') do - = link_to activity_group_path(@group), title: 'Activity' do - %span - Activity - -.hidden-xs - = render "projects/last_push" diff --git a/app/views/groups/_head_issues.html.haml b/app/views/groups/_head_issues.html.haml deleted file mode 100644 index d554bc23743..00000000000 --- a/app/views/groups/_head_issues.html.haml +++ /dev/null @@ -1,19 +0,0 @@ -= content_for :sub_nav do - .scrolling-tabs-container.sub-nav-scroll - = render 'shared/nav_scroll' - .nav-links.sub-nav.scrolling-tabs - %ul{ class: container_class } - = nav_link(path: 'groups#issues', html_options: { class: 'home' }) do - = link_to issues_group_path(@group), title: 'List' do - %span - List - - = nav_link(path: 'labels#index') do - = link_to group_labels_path(@group), title: 'Labels' do - %span - Labels - - = nav_link(path: 'milestones#index') do - = link_to group_milestones_path(@group), title: 'Milestones' do - %span - Milestones diff --git a/app/views/groups/_settings_head.html.haml b/app/views/groups/_settings_head.html.haml deleted file mode 100644 index 623d233a46a..00000000000 --- a/app/views/groups/_settings_head.html.haml +++ /dev/null @@ -1,19 +0,0 @@ -= content_for :sub_nav do - .scrolling-tabs-container.sub-nav-scroll - = render 'shared/nav_scroll' - .nav-links.sub-nav.scrolling-tabs - %ul{ class: container_class } - = nav_link(path: 'groups#edit') do - = link_to edit_group_path(@group), title: 'General' do - %span - General - - = nav_link(path: 'groups#projects') do - = link_to projects_group_path(@group), title: 'Projects' do - %span - Projects - - = nav_link(controller: :ci_cd) do - = link_to group_settings_ci_cd_path(@group), title: 'Pipelines' do - %span - Pipelines diff --git a/app/views/groups/activity.html.haml b/app/views/groups/activity.html.haml index 3969e56f937..cb7dab26332 100644 --- a/app/views/groups/activity.html.haml +++ b/app/views/groups/activity.html.haml @@ -2,7 +2,6 @@ = auto_discovery_link_tag(:atom, group_url(@group, rss_url_options), title: "#{@group.name} activity") - page_title "Activity" -= render 'groups/head' %section.activities = render 'activities' diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml index 0d3308833b7..15606dd30fd 100644 --- a/app/views/groups/edit.html.haml +++ b/app/views/groups/edit.html.haml @@ -1,5 +1,4 @@ - breadcrumb_title "General Settings" -= render "groups/settings_head" .panel.panel-default.prepend-top-default .panel-heading Group settings diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml index 7f411927429..07e64d9aeaf 100644 --- a/app/views/groups/issues.html.haml +++ b/app/views/groups/issues.html.haml @@ -1,6 +1,5 @@ - page_title "Issues" - group_issues_exists = group_issues(@group).exists? -= render "head_issues" = content_for :meta_tags do = auto_discovery_link_tag(:atom, params.merge(rss_url_options), title: "#{@group.name} issues") diff --git a/app/views/groups/labels/index.html.haml b/app/views/groups/labels/index.html.haml index 89165096fe2..d10efdad53b 100644 --- a/app/views/groups/labels/index.html.haml +++ b/app/views/groups/labels/index.html.haml @@ -1,8 +1,5 @@ - page_title 'Labels' -= render "groups/head_issues" - - .top-area.adjust .nav-text Labels can be applied to issues and merge requests. Group labels are available for any project within the group. diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index ed582e521c4..cb4fc69d5b8 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -1,7 +1,5 @@ - page_title "Milestones" -= render "groups/head_issues" - .top-area = render 'shared/milestones_filter', counts: @milestone_states diff --git a/app/views/groups/projects.html.haml b/app/views/groups/projects.html.haml index 7f3f2f707f7..8d2bc810a7d 100644 --- a/app/views/groups/projects.html.haml +++ b/app/views/groups/projects.html.haml @@ -1,5 +1,4 @@ - breadcrumb_title "Projects" -= render "groups/settings_head" .panel.panel-default.prepend-top-default .panel-heading diff --git a/app/views/groups/settings/ci_cd/show.html.haml b/app/views/groups/settings/ci_cd/show.html.haml index 9f9ae01e7c5..472da2a6a72 100644 --- a/app/views/groups/settings/ci_cd/show.html.haml +++ b/app/views/groups/settings/ci_cd/show.html.haml @@ -1,5 +1,4 @@ - breadcrumb_title "CI / CD Settings" - page_title "CI / CD" -= render "groups/settings_head" = render 'ci/variables/index' diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index f4f76887422..3ca63f9c3e0 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -4,7 +4,6 @@ = content_for :meta_tags do = auto_discovery_link_tag(:atom, group_url(@group, rss_url_options), title: "#{@group.name} activity") -= render 'groups/head' = render 'groups/home_panel' .groups-header{ class: container_class } diff --git a/app/views/groups/subgroups.html.haml b/app/views/groups/subgroups.html.haml index 7abc84412c6..869b3b243c6 100644 --- a/app/views/groups/subgroups.html.haml +++ b/app/views/groups/subgroups.html.haml @@ -1,7 +1,6 @@ - breadcrumb_title "Details" - @no_container = true -= render 'head' = render 'groups/home_panel' .groups-header{ class: container_class } diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml index e6a10e500a4..0d5350f873b 100644 --- a/app/views/layouts/_head.html.haml +++ b/app/views/layouts/_head.html.haml @@ -32,18 +32,14 @@ = stylesheet_link_tag "test", media: "all" if Rails.env.test? = stylesheet_link_tag 'performance_bar' if performance_bar_enabled? - // TODO: Combine these 2 stylesheets into application.scss - = stylesheet_link_tag "new_nav", media: "all" - = stylesheet_link_tag "new_sidebar", media: "all" - = Gon::Base.render_data - if content_for?(:library_javascripts) = yield :library_javascripts + = javascript_include_tag asset_path("locale/#{I18n.locale.to_s || I18n.default_locale.to_s}/app.js") = webpack_bundle_tag "webpack_runtime" = webpack_bundle_tag "common" - = webpack_bundle_tag "locale" = webpack_bundle_tag "main" = webpack_bundle_tag "raven" if current_application_settings.clientside_sentry_enabled = webpack_bundle_tag "test" if Rails.env.test? diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml index cd7a47da4a1..29387d6627e 100644 --- a/app/views/layouts/_search.html.haml +++ b/app/views/layouts/_search.html.haml @@ -21,8 +21,8 @@ %a Loading... = dropdown_loading - %i.search-icon - %i.clear-icon.js-clear-input + = sprite_icon('search', size: 16, css_class: 'search-icon') + = sprite_icon('close', size: 16, css_class: 'clear-icon js-clear-input') = hidden_field_tag :group_id, @group.try(:id), class: 'js-search-group-options', data: group_data_attrs diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index d8fc371497d..7e9b76da570 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -22,29 +22,29 @@ = render 'layouts/search' unless current_controller?(:search) %li.visible-sm-inline-block.visible-xs-inline-block = link_to search_path, title: 'Search', aria: { label: "Search" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do - = icon('search') + = sprite_icon('search', size: 16) - if current_user - %li.user-counter + = nav_link(path: 'dashboard#issues', html_options: { class: "user-counter" }) do = link_to assigned_issues_dashboard_path, title: 'Issues', class: 'dashboard-shortcuts-issues', aria: { label: "Issues" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do - = custom_icon('issues') + = sprite_icon('issues', size: 16) - issues_count = assigned_issuables_count(:issues) %span.badge.issues-count{ class: ('hidden' if issues_count.zero?) } = number_with_delimiter(issues_count) - %li.user-counter + = nav_link(path: 'dashboard#merge_requests', html_options: { class: "user-counter" }) do = link_to assigned_mrs_dashboard_path, title: 'Merge requests', class: 'dashboard-shortcuts-merge_requests', aria: { label: "Merge requests" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do - = custom_icon('mr_bold') + = sprite_icon('git-merge', size: 16) - merge_requests_count = assigned_issuables_count(:merge_requests) %span.badge.merge-requests-count{ class: ('hidden' if merge_requests_count.zero?) } = number_with_delimiter(merge_requests_count) - %li.user-counter + = nav_link(controller: 'dashboard/todos', html_options: { class: "user-counter" }) do = link_to dashboard_todos_path, title: 'Todos', aria: { label: "Todos" }, class: 'shortcuts-todos', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do - = custom_icon('todo_done') + = sprite_icon('todo-done', size: 16) %span.badge.todos-count{ class: ('hidden' if todos_pending_count.zero?) } = todos_count_format(todos_pending_count) %li.header-user.dropdown = link_to current_user, class: user_dropdown_class, data: { toggle: "dropdown" } do = image_tag avatar_icon(current_user, 23), width: 23, height: 23, class: "header-user-avatar" - = custom_icon('caret_down') + = sprite_icon('angle-down', css_class: 'caret-down') .dropdown-menu-nav.dropdown-menu-align-right %ul %li.current-user @@ -73,7 +73,7 @@ %button.navbar-toggle.hidden-sm.hidden-md.hidden-lg{ type: 'button' } %span.sr-only Toggle navigation - = icon('ellipsis-v', class: 'js-navbar-toggle-right') - = icon('times', class: 'js-navbar-toggle-left') + = sprite_icon('more', size: 16, css_class: 'more-icon js-navbar-toggle-right') + = sprite_icon('close', size: 16, css_class: 'close-icon js-navbar-toggle-left') = render 'shared/outdated_browser' diff --git a/app/views/layouts/header/_new_dropdown.haml b/app/views/layouts/header/_new_dropdown.haml index 63d1c077ecd..088f2785092 100644 --- a/app/views/layouts/header/_new_dropdown.haml +++ b/app/views/layouts/header/_new_dropdown.haml @@ -1,7 +1,7 @@ %li.header-new.dropdown = link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip", title: "New...", ref: 'tooltip', aria: { label: "New..." }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body' } do - = custom_icon('plus_square') - = custom_icon('caret_down') + = sprite_icon('plus-square', size: 16) + = sprite_icon('angle-down', css_class: 'caret-down') .dropdown-menu-nav.dropdown-menu-align-right %ul - if @group&.persisted? diff --git a/app/views/layouts/nav/_breadcrumbs.html.haml b/app/views/layouts/nav/_breadcrumbs.html.haml index 7bd3f5306a2..002922e13f1 100644 --- a/app/views/layouts/nav/_breadcrumbs.html.haml +++ b/app/views/layouts/nav/_breadcrumbs.html.haml @@ -16,5 +16,5 @@ = breadcrumb_list_item link_to(extra[:text], extra[:link]) = render "layouts/nav/breadcrumbs/collapsed_dropdown", location: :after %li - %h2.breadcrumbs-sub-title= @breadcrumb_title + %h2.breadcrumbs-sub-title= link_to @breadcrumb_title, breadcrumb_title_link = yield :header_content diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml index c254ee02dd8..e0d8d9cb402 100644 --- a/app/views/layouts/nav/_dashboard.html.haml +++ b/app/views/layouts/nav/_dashboard.html.haml @@ -2,7 +2,7 @@ = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: { id: 'nav-projects-dropdown', class: "home dropdown header-projects" }) do %a{ href: "#", data: { toggle: "dropdown" } } Projects - = custom_icon('caret_down') + = sprite_icon('angle-down', css_class: 'caret-down') .dropdown-menu.projects-dropdown-menu = render "layouts/nav/projects_dropdown/show" @@ -25,7 +25,7 @@ %li.header-more.dropdown.hidden-lg %a{ href: "#", data: { toggle: "dropdown" } } More - = custom_icon('caret_down') + = sprite_icon('angle-down', css_class: 'caret-down') .dropdown-menu %ul = nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { class: "visible-xs" }) do @@ -54,7 +54,7 @@ - if current_user.admin? = nav_link(controller: 'admin/dashboard') do = link_to admin_root_path, class: 'admin-icon', title: 'Admin area', aria: { label: "Admin area" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do - = icon('wrench fw') + = sprite_icon('admin', size: 18) - if Gitlab::Sherlock.enabled? %li = link_to sherlock_transactions_path, class: 'admin-icon', title: 'Sherlock Transactions', diff --git a/app/views/layouts/nav/breadcrumbs/_collapsed_dropdown.html.haml b/app/views/layouts/nav/breadcrumbs/_collapsed_dropdown.html.haml index 28022eebb19..610ff9001f7 100644 --- a/app/views/layouts/nav/breadcrumbs/_collapsed_dropdown.html.haml +++ b/app/views/layouts/nav/breadcrumbs/_collapsed_dropdown.html.haml @@ -4,7 +4,7 @@ %li.dropdown %button.text-expander.has-tooltip.js-breadcrumbs-collapsed-expander{ type: "button", data: { toggle: "dropdown", container: "body" }, "aria-label": button_tooltip, title: button_tooltip } = icon("ellipsis-h") - = icon("angle-right", class: "breadcrumbs-list-angle") + = sprite_icon("angle-right", css_class: "breadcrumbs-list-angle") .dropdown-menu %ul - @breadcrumb_dropdown_links[dropdown_location].each_with_index do |link, index| diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml index 9eef006b6a8..0ec07605631 100644 --- a/app/views/layouts/nav/sidebar/_admin.html.haml +++ b/app/views/layouts/nav/sidebar/_admin.html.haml @@ -3,7 +3,7 @@ .context-header = link_to admin_root_path, title: 'Admin Overview' do .avatar-container.s40.settings-avatar - = icon('wrench') + = sprite_icon('admin', size: 24) .sidebar-context-title Admin Area %ul.sidebar-top-level-items = nav_link(controller: %w(dashboard admin projects users groups jobs runners cohorts conversational_development_index), html_options: {class: 'home'}) do @@ -12,7 +12,6 @@ = sprite_icon('overview') %span.nav-item-name Overview - %ul.sidebar-sub-level-items = nav_link(controller: %w(dashboard admin projects users groups jobs runners cohorts conversational_development_index), html_options: { class: "fly-out-top-item" } ) do = link_to admin_root_path do diff --git a/app/views/layouts/nav/sidebar/_profile.html.haml b/app/views/layouts/nav/sidebar/_profile.html.haml index a015c94c60e..458b5010d36 100644 --- a/app/views/layouts/nav/sidebar/_profile.html.haml +++ b/app/views/layouts/nav/sidebar/_profile.html.haml @@ -3,7 +3,7 @@ .context-header = link_to profile_path, title: 'Profile Settings' do .avatar-container.s40.settings-avatar - = icon('user') + = sprite_icon('user', size: 24) .sidebar-context-title User Settings %ul.sidebar-top-level-items = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do diff --git a/app/views/projects/_head.html.haml b/app/views/projects/_head.html.haml deleted file mode 100644 index dba84838a52..00000000000 --- a/app/views/projects/_head.html.haml +++ /dev/null @@ -1,17 +0,0 @@ -= content_for :sub_nav do - .scrolling-tabs-container.sub-nav-scroll - = render 'shared/nav_scroll' - .nav-links.sub-nav.scrolling-tabs - %ul{ class: container_class } - = nav_link(path: 'projects#show') do - = link_to project_path(@project), title: _('Project home'), class: 'shortcuts-project' do - %span= _('Home') - - = nav_link(path: 'projects#activity') do - = link_to activity_project_path(@project), title: _('Activity'), class: 'shortcuts-project-activity' do - %span= _('Activity') - - - if can?(current_user, :read_cycle_analytics, @project) - = nav_link(path: 'cycle_analytics#show') do - = link_to project_cycle_analytics_path(@project), title: _('Cycle Analytics'), class: 'shortcuts-project-cycle-analytics' do - %span= _('Cycle Analytics') diff --git a/app/views/projects/_merge_request_fast_forward_settings.html.haml b/app/views/projects/_merge_request_fast_forward_settings.html.haml new file mode 100644 index 00000000000..9d357293a2f --- /dev/null +++ b/app/views/projects/_merge_request_fast_forward_settings.html.haml @@ -0,0 +1,13 @@ +- form = local_assigns.fetch(:form) +- project = local_assigns.fetch(:project) + +.radio + = label_tag :project_merge_method_ff do + = form.radio_button :merge_method, :ff, class: "js-merge-method-radio" + %strong Fast-forward merge + %br + %span.descr + No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. + %br + %span.descr + When fast-forward merge is not possible, the user must first rebase locally. diff --git a/app/views/projects/_merge_request_rebase_settings.html.haml b/app/views/projects/_merge_request_rebase_settings.html.haml new file mode 100644 index 00000000000..c52e09573a6 --- /dev/null +++ b/app/views/projects/_merge_request_rebase_settings.html.haml @@ -0,0 +1,13 @@ +- form = local_assigns.fetch(:form) + +.radio + = label_tag :project_merge_method_rebase_merge do + = form.radio_button :merge_method, :rebase_merge, class: "js-merge-method-radio" + %strong Merge commit with semi-linear history + %br + %span.descr + A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. + This way you could make sure that if this merge request would build, after merging to target branch it would also build. + %br + %span.descr + When fast-forward merge is not possible, the user must first rebase locally. diff --git a/app/views/projects/_merge_request_settings.html.haml b/app/views/projects/_merge_request_settings.html.haml index cc5afa943cf..fd0c419cdac 100644 --- a/app/views/projects/_merge_request_settings.html.haml +++ b/app/views/projects/_merge_request_settings.html.haml @@ -1,3 +1,18 @@ - form = local_assigns.fetch(:form) +.form-group + = label_tag :merge_method_merge, class: 'label-light' do + Merge method + .radio + = label_tag :project_merge_method_merge do + = form.radio_button :merge_method, :merge, class: "js-merge-method-radio" + %strong Merge commit + %br + %span.descr + A merge commit is created for every merge, and merging is allowed as long as there are no conflicts. + + = render 'merge_request_rebase_settings', form: form + + = render 'merge_request_fast_forward_settings', project: @project, form: form + = render 'projects/merge_request_merge_settings', form: form diff --git a/app/views/projects/activity.html.haml b/app/views/projects/activity.html.haml index f80dadb8037..d0ab39033cf 100644 --- a/app/views/projects/activity.html.haml +++ b/app/views/projects/activity.html.haml @@ -2,8 +2,6 @@ - page_title _("Activity") -= render "projects/head" - = render 'projects/last_push' = render 'projects/activity' diff --git a/app/views/projects/artifacts/browse.html.haml b/app/views/projects/artifacts/browse.html.haml index 4cc3218d967..fe02cbcbf95 100644 --- a/app/views/projects/artifacts/browse.html.haml +++ b/app/views/projects/artifacts/browse.html.haml @@ -1,10 +1,9 @@ - breadcrumb_title _('Artifacts') - page_title @path.presence, 'Artifacts', "#{@build.name} (##{@build.id})", 'Jobs' -= render "projects/pipelines/head" = render "projects/jobs/header", show_controls: false -- add_to_breadcrumbs(_('Jobs'), project_jobs_path(@project)) +- add_to_breadcrumbs(s_('CICD|Jobs'), project_jobs_path(@project)) - add_to_breadcrumbs("##{@build.id}", project_jobs_path(@project)) .tree-holder diff --git a/app/views/projects/artifacts/file.html.haml b/app/views/projects/artifacts/file.html.haml index b85bbcb980e..2942d618a42 100644 --- a/app/views/projects/artifacts/file.html.haml +++ b/app/views/projects/artifacts/file.html.haml @@ -1,5 +1,4 @@ - page_title @path, 'Artifacts', "#{@build.name} (##{@build.id})", 'Jobs' -= render "projects/pipelines/head" = render "projects/jobs/header", show_controls: false diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml index 60ac202bde0..e45861ac08d 100644 --- a/app/views/projects/blame/show.html.haml +++ b/app/views/projects/blame/show.html.haml @@ -1,7 +1,6 @@ - @no_container = true - project_duration = age_map_duration(@blame_groups, @project) - page_title "Blame", @blob.path, @ref -= render "projects/commits/head" %div{ class: container_class } #blob-content-holder.tree-holder diff --git a/app/views/projects/blob/diff.html.haml b/app/views/projects/blob/diff.html.haml index d1d448f0d4c..ea7a71792a3 100644 --- a/app/views/projects/blob/diff.html.haml +++ b/app/views/projects/blob/diff.html.haml @@ -5,25 +5,24 @@ = diff_match_line @form.since, @form.since, text: @match_line, view: diff_view - @lines.each_with_index do |line, index| - - line_new = index + @form.since - - line_old = line_new - @form.offset - - line_content = capture do - %td.line_content.noteable_line{ class: line_class }==#{' ' * @form.indent}#{line} - %tr.line_holder.diff-expanded{ id: line_old, class: line_class } + - line_number_new = index + @form.since + - line_number_old = line_number_new - @form.offset + - line[0, 0] = ' ' * @form.indent + %tr.line_holder.diff-expanded{ id: line_number_old, class: line_class } - case diff_view - when :inline - %td.old_line.diff-line-num{ data: { linenumber: line_old } } - %a{ href: "#", data: { linenumber: line_old }, disabled: true } - %td.new_line.diff-line-num{ data: { linenumber: line_new } } - %a{ href: "#", data: { linenumber: line_new }, disabled: true } - = line_content + %td.old_line.diff-line-num{ data: { linenumber: line_number_old } } + %a{ href: "#", data: { linenumber: line_number_old }, disabled: true } + %td.new_line.diff-line-num{ data: { linenumber: line_number_new } } + %a{ href: "#", data: { linenumber: line_number_new }, disabled: true } + %td.line_content.noteable_line{ class: line_class }= line - when :parallel - %td.old_line.diff-line-num{ data: { linenumber: line_old } } - %a{ href: "##{line_old}", data: { linenumber: line_old }, disabled: true } - = line_content - %td.new_line.diff-line-num{ data: { linenumber: line_new } } - %a{ href: "##{line_new}", data: { linenumber: line_new }, disabled: true } - = line_content + %td.old_line.diff-line-num{ data: { linenumber: line_number_old } } + %a{ href: "##{line_number_old}", data: { linenumber: line_number_old }, disabled: true } + %td.line_content.noteable_line.left-side{ class: line_class }= line + %td.new_line.diff-line-num{ data: { linenumber: line_number_new } } + %a{ href: "##{line_number_new}", data: { linenumber: line_number_new }, disabled: true } + %td.line_content.noteable_line.right-side{ class: line_class }= line - if @form.unfold? && @form.bottom? && @form.to < @blob.lines.size %tr.line_holder{ id: @form.to, class: line_class } diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml index 992fe7f717f..626cbc9e41d 100644 --- a/app/views/projects/blob/edit.html.haml +++ b/app/views/projects/blob/edit.html.haml @@ -4,7 +4,6 @@ - content_for :page_specific_javascripts do = page_specific_javascript_tag('lib/ace.js') = page_specific_javascript_bundle_tag('blob') -= render "projects/commits/head" %div{ class: container_class } - if @conflict diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml index 240e62d5ac5..c4712bf3736 100644 --- a/app/views/projects/blob/show.html.haml +++ b/app/views/projects/blob/show.html.haml @@ -2,7 +2,6 @@ - @no_container = true - page_title @blob.path, @ref -= render "projects/commits/head" - content_for :page_specific_javascripts do = webpack_bundle_tag 'blob' diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml index ea6e7e9db6c..7d9645d79e6 100644 --- a/app/views/projects/branches/index.html.haml +++ b/app/views/projects/branches/index.html.haml @@ -1,6 +1,5 @@ - @no_container = true - page_title _('Branches') -= render "projects/commits/head" %div{ class: container_class } .top-area.adjust diff --git a/app/views/projects/buttons/_fork.html.haml b/app/views/projects/buttons/_fork.html.haml index f45cc7f0f45..f880556a9f7 100644 --- a/app/views/projects/buttons/_fork.html.haml +++ b/app/views/projects/buttons/_fork.html.haml @@ -4,12 +4,11 @@ = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: _('Go to your fork'), class: 'btn has-tooltip' do = custom_icon('icon_fork') %span= s_('GoToYourFork|Fork') - - elsif !current_user.can_create_project? - = link_to new_project_fork_path(@project), title: _('You have reached your project limit'), class: 'btn has-tooltip disabled' do - = custom_icon('icon_fork') - %span= s_('CreateNewFork|Fork') - else - = link_to new_project_fork_path(@project), class: 'btn' do + - can_create_fork = current_user.can?(:create_fork) + = link_to new_project_fork_path(@project), + class: "btn btn-default #{'has-tooltip disabled' unless can_create_fork}", + title: (_('You have reached your project limit') unless can_create_fork) do = custom_icon('icon_fork') %span= s_('CreateNewFork|Fork') .count-with-arrow diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml index 717de85c5d2..abb292f8f27 100644 --- a/app/views/projects/commit/show.html.haml +++ b/app/views/projects/commit/show.html.haml @@ -6,7 +6,6 @@ - @content_class = limited_container_width - page_title "#{@commit.title} (#{@commit.short_id})", "Commits" - page_description @commit.description -= render "projects/commits/head" .container-fluid{ class: [limited_container_width, container_class] } = render "commit_box" diff --git a/app/views/projects/commits/_head.html.haml b/app/views/projects/commits/_head.html.haml deleted file mode 100644 index e1549baef89..00000000000 --- a/app/views/projects/commits/_head.html.haml +++ /dev/null @@ -1,36 +0,0 @@ -= content_for :sub_nav do - .scrolling-tabs-container.sub-nav-scroll - = render 'shared/nav_scroll' - .nav-links.sub-nav.scrolling-tabs - %ul{ class: (container_class) } - = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file)) do - = link_to project_tree_path(@project) do - #{ _('Files') } - - = nav_link(controller: [:commit, :commits]) do - = link_to project_commits_path(@project, current_ref) do - #{ _('Commits') } - - = nav_link(html_options: {class: branches_tab_class}) do - = link_to project_branches_path(@project) do - #{ _('Branches') } - - = nav_link(controller: [:tags, :releases]) do - = link_to project_tags_path(@project) do - #{ _('Tags') } - - = nav_link(path: 'graphs#show') do - = link_to project_graph_path(@project, current_ref) do - #{ _('Contributors') } - - = nav_link(controller: %w(network)) do - = link_to project_network_path(@project, current_ref) do - #{ s_('ProjectNetworkGraph|Graph') } - - = nav_link(controller: :compare) do - = link_to project_compare_index_path(@project, from: @repository.root_ref, to: current_ref) do - #{ _('Compare') } - - = nav_link(path: 'graphs#charts') do - = link_to charts_project_graph_path(@project, current_ref) do - #{ _('Charts') } diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml index e873b931683..ef305120525 100644 --- a/app/views/projects/commits/show.html.haml +++ b/app/views/projects/commits/show.html.haml @@ -5,9 +5,6 @@ = content_for :meta_tags do = auto_discovery_link_tag(:atom, project_commits_url(@project, @ref, rss_url_options), title: "#{@project.name}:#{@ref} commits") -= content_for :sub_nav do - = render "head" - .js-project-commits-show{ 'data-commits-limit' => @limit } %div{ class: container_class } .tree-holder diff --git a/app/views/projects/compare/index.html.haml b/app/views/projects/compare/index.html.haml index 1ce3ad0c0fd..3ad0166e9cd 100644 --- a/app/views/projects/compare/index.html.haml +++ b/app/views/projects/compare/index.html.haml @@ -1,7 +1,6 @@ - @no_container = true - breadcrumb_title "Compare Revisions" - page_title "Compare" -= render "projects/commits/head" %div{ class: container_class } .sub-header-block diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml index 7cc42455394..f87f1d476f5 100644 --- a/app/views/projects/compare/show.html.haml +++ b/app/views/projects/compare/show.html.haml @@ -1,7 +1,6 @@ - @no_container = true - add_to_breadcrumbs "Compare Revisions", project_compare_index_path(@project) - page_title "#{params[:from]}...#{params[:to]}" -= render "projects/commits/head" %div{ class: container_class } .sub-header-block.no-bottom-space diff --git a/app/views/projects/cycle_analytics/show.html.haml b/app/views/projects/cycle_analytics/show.html.haml index 8d008be5aae..c06e9f323af 100644 --- a/app/views/projects/cycle_analytics/show.html.haml +++ b/app/views/projects/cycle_analytics/show.html.haml @@ -4,8 +4,6 @@ = page_specific_javascript_bundle_tag('common_vue') = page_specific_javascript_bundle_tag('cycle_analytics') -= render "projects/head" - #cycle-analytics{ class: container_class, "v-cloak" => "true", data: { request_path: project_cycle_analytics_path(@project) } } - if @cycle_analytics_no_data .landing.content-block{ "v-if" => "!isOverviewDialogDismissed" } diff --git a/app/views/projects/diffs/_parallel_view.html.haml b/app/views/projects/diffs/_parallel_view.html.haml index 56d63250714..1f0ca211074 100644 --- a/app/views/projects/diffs/_parallel_view.html.haml +++ b/app/views/projects/diffs/_parallel_view.html.haml @@ -14,20 +14,20 @@ = diff_match_line left.old_pos, nil, text: left.text, view: :parallel - when 'old-nonewline', 'new-nonewline' %td.old_line.diff-line-num - %td.line_content.match= left.text + %td.line_content.match.left-side= left.text - else - left_line_code = diff_file.line_code(left) - left_position = diff_file.position(left) - %td.old_line.diff-line-num.js-avatar-container{ id: left_line_code, class: left.type, data: { linenumber: left.old_pos } } + %td.old_line.diff-line-num.js-avatar-container{ class: left.type, data: { linenumber: left.old_pos } } = add_diff_note_button(left_line_code, left_position, 'old') %a{ href: "##{left_line_code}", data: { linenumber: left.old_pos } } - discussion_left = discussions_left.try(:first) - if discussion_left && discussion_left.resolvable? %diff-note-avatars{ "discussion-id" => discussion_left.id } - %td.line_content.parallel.noteable_line{ class: left.type }= diff_line_content(left.text) + %td.line_content.parallel.noteable_line.left-side{ id: left_line_code, class: left.type }= diff_line_content(left.text) - else %td.old_line.diff-line-num.empty-cell - %td.line_content.parallel + %td.line_content.parallel.left-side - if right - case right.type @@ -35,20 +35,20 @@ = diff_match_line nil, right.new_pos, text: left.text, view: :parallel - when 'old-nonewline', 'new-nonewline' %td.new_line.diff-line-num - %td.line_content.match= right.text + %td.line_content.match.right-side= right.text - else - right_line_code = diff_file.line_code(right) - right_position = diff_file.position(right) - %td.new_line.diff-line-num.js-avatar-container{ id: right_line_code, class: right.type, data: { linenumber: right.new_pos } } + %td.new_line.diff-line-num.js-avatar-container{ class: right.type, data: { linenumber: right.new_pos } } = add_diff_note_button(right_line_code, right_position, 'new') %a{ href: "##{right_line_code}", data: { linenumber: right.new_pos } } - discussion_right = discussions_right.try(:first) - if discussion_right && discussion_right.resolvable? %diff-note-avatars{ "discussion-id" => discussion_right.id } - %td.line_content.parallel.noteable_line{ class: right.type }= diff_line_content(right.text) + %td.line_content.parallel.noteable_line.right-side{ id: right_line_code, class: right.type }= diff_line_content(right.text) - else %td.old_line.diff-line-num.empty-cell - %td.line_content.parallel + %td.line_content.parallel.right-side - if discussions_left || discussions_right = render "discussions/parallel_diff_discussion", discussions_left: discussions_left, discussions_right: discussions_right diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 0a3045604f4..8ae4fd94146 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -3,8 +3,6 @@ - @content_class = "limit-container-width" unless fluid_layout - expanded = Rails.env.test? -= render "projects/settings/head" - .project-edit-container %section.settings.general-settings .settings-header diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml index d5b83b53ebb..3f3ce10419f 100644 --- a/app/views/projects/empty.html.haml +++ b/app/views/projects/empty.html.haml @@ -3,7 +3,6 @@ = render partial: 'flash_messages', locals: { project: @project } -= render "projects/head" = render "home_panel" .row-content-block.second-block.center diff --git a/app/views/projects/environments/edit.html.haml b/app/views/projects/environments/edit.html.haml index 3871165763c..d6ff3f729b4 100644 --- a/app/views/projects/environments/edit.html.haml +++ b/app/views/projects/environments/edit.html.haml @@ -1,6 +1,5 @@ - @no_container = true - page_title "Edit", @environment.name, "Environments" -= render "projects/pipelines/head" %div{ class: container_class } %h3.page-title diff --git a/app/views/projects/environments/folder.html.haml b/app/views/projects/environments/folder.html.haml index f7e3733ba0b..1bcc955ddc8 100644 --- a/app/views/projects/environments/folder.html.haml +++ b/app/views/projects/environments/folder.html.haml @@ -1,6 +1,5 @@ - @no_container = true - page_title "Environments" -= render "projects/pipelines/head" - content_for :page_specific_javascripts do = page_specific_javascript_bundle_tag('common_vue') diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml index acc80b49dd0..2e85f608823 100644 --- a/app/views/projects/environments/index.html.haml +++ b/app/views/projects/environments/index.html.haml @@ -1,7 +1,6 @@ - @no_container = true - page_title "Environments" - add_to_breadcrumbs("Pipelines", project_pipelines_path(@project)) -= render "projects/pipelines/head" - content_for :page_specific_javascripts do = page_specific_javascript_bundle_tag('common_vue') diff --git a/app/views/projects/environments/metrics.html.haml b/app/views/projects/environments/metrics.html.haml index 4a65b46f029..e0aedcac5e1 100644 --- a/app/views/projects/environments/metrics.html.haml +++ b/app/views/projects/environments/metrics.html.haml @@ -4,7 +4,6 @@ = webpack_bundle_tag 'common_vue' = webpack_bundle_tag 'common_d3' = webpack_bundle_tag 'monitoring' -= render "projects/pipelines/head" .prometheus-container{ class: container_class } .top-area @@ -21,4 +20,3 @@ "empty-unable-to-connect-svg-path": image_path('illustrations/monitoring/unable_to_connect'), "additional-metrics": additional_metrics_project_environment_path(@project, @environment, format: :json), "has-metrics": "#{@environment.has_metrics?}", deployment_endpoint: project_environment_deployments_path(@project, @environment, format: :json) } } - diff --git a/app/views/projects/environments/new.html.haml b/app/views/projects/environments/new.html.haml index 88f43a1e7e4..62b08e85e22 100644 --- a/app/views/projects/environments/new.html.haml +++ b/app/views/projects/environments/new.html.haml @@ -1,7 +1,6 @@ - @no_container = true - breadcrumb_title "Environments" - page_title 'New Environment' -= render "projects/pipelines/head" %div{ class: container_class } %h3.page-title diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml index c35d1b5aaee..d7859c9fbeb 100644 --- a/app/views/projects/environments/show.html.haml +++ b/app/views/projects/environments/show.html.haml @@ -2,7 +2,6 @@ - add_to_breadcrumbs "Environments", project_environments_path(@project) - breadcrumb_title @environment.name - page_title "Environments" -= render "projects/pipelines/head" %div{ class: container_class } .row.top-area.adjust diff --git a/app/views/projects/environments/terminal.html.haml b/app/views/projects/environments/terminal.html.haml index 464135b5ac7..a073a164f11 100644 --- a/app/views/projects/environments/terminal.html.haml +++ b/app/views/projects/environments/terminal.html.haml @@ -1,6 +1,5 @@ - @no_container = true - page_title "Terminal for environment", @environment.name -= render "projects/pipelines/head" - content_for :page_specific_javascripts do = stylesheet_link_tag "xterm/xterm" diff --git a/app/views/projects/find_file/show.html.haml b/app/views/projects/find_file/show.html.haml index 021575160ea..a3467eb6f05 100644 --- a/app/views/projects/find_file/show.html.haml +++ b/app/views/projects/find_file/show.html.haml @@ -1,5 +1,4 @@ - page_title "Find File", @ref -= render "projects/commits/head" .file-finder-holder.tree-holder.clearfix.js-file-finder{ 'data-file-find-url': "#{escape_javascript(project_files_path(@project, @ref, @options.merge(format: :json)))}", 'data-find-tree-url': escape_javascript(project_tree_path(@project, @ref)), 'data-blob-url-template': escape_javascript(project_blob_path(@project, @id || @commit.id)) } .nav-block diff --git a/app/views/projects/forks/new.html.haml b/app/views/projects/forks/new.html.haml index 0f36e1a7353..e9613534dde 100644 --- a/app/views/projects/forks/new.html.haml +++ b/app/views/projects/forks/new.html.haml @@ -9,46 +9,36 @@ %br Forking a repository allows you to make changes without affecting the original project. .col-lg-9 - .fork-namespaces - - if @namespaces.present? - %label.label-light - %span - Click to fork the project to a user or group - - @namespaces.in_groups_of(6, false) do |group| - .row - - group.each do |namespace| - - avatar = namespace_icon(namespace, 100) - - if fork = namespace.find_fork_of(@project) - .fork-thumbnail.forked - = link_to project_path(fork) do - - if /no_((\w*)_)*avatar/.match(avatar) - .no-avatar - = icon 'question' - - else - = image_tag avatar - .caption - = namespace.human_name - - else - .fork-thumbnail - = link_to project_forks_path(@project, namespace_key: namespace.id), method: "POST" do - - if /no_((\w*)_)*avatar/.match(avatar) - .no-avatar - = icon 'question' - - else - = image_tag avatar - .caption - = namespace.human_name - - else - %label.label-light - %span - No available namespaces to fork the project. - %br - %small - You must have permission to create a project in a namespace before forking. + - if @namespaces.present? + .fork-thumbnail-container.js-fork-content + %h5.prepend-top-0.append-bottom-0.prepend-left-default.append-right-default + Click to fork the project + - @namespaces.each do |namespace| + - avatar = namespace_icon(namespace, 100) + - can_create_project = current_user.can?(:create_projects, namespace) + - forked_project = namespace.find_fork_of(@project) + - fork_path = forked_project ? project_path(forked_project) : project_forks_path(@project, namespace_key: namespace.id) + .bordered-box.fork-thumbnail.text-center.prepend-left-default.append-right-default.prepend-top-default.append-bottom-default{ class: [("disabled" unless can_create_project), ("forked" if forked_project)] } + = link_to fork_path, + method: "POST", + class: [("js-fork-thumbnail" unless forked_project), ("disabled has-tooltip" unless can_create_project)], + title: (_('You have reached your project limit') unless can_create_project) do + - if /no_((\w*)_)*avatar/.match(avatar) + = project_identicon(namespace, class: "avatar s100 identicon") + - else + .avatar-container.s100 + = image_tag(avatar, class: "avatar s100") + %h5.prepend-top-default + = namespace.human_name + - else + %strong + No available namespaces to fork the project. + %p.prepend-top-default + You must have permission to create a project in a namespace before forking. - .save-project-loader.hide - .center - %h2 - %i.fa.fa-spinner.fa-spin - Forking repository - %p Please wait a moment, this page will automatically refresh when ready. + .save-project-loader.hide.js-fork-content + %h2.text-center + = icon('spinner spin') + Forking repository + %p.text-center + Please wait a moment, this page will automatically refresh when ready. diff --git a/app/views/projects/graphs/charts.html.haml b/app/views/projects/graphs/charts.html.haml index f0ef647ddb3..ffb9238a65a 100644 --- a/app/views/projects/graphs/charts.html.haml +++ b/app/views/projects/graphs/charts.html.haml @@ -4,7 +4,6 @@ = webpack_bundle_tag('common_d3') = webpack_bundle_tag('graphs') = webpack_bundle_tag('graphs_charts') -= render "projects/commits/head" .repo-charts{ class: container_class } %h4.sub-header diff --git a/app/views/projects/graphs/show.html.haml b/app/views/projects/graphs/show.html.haml index 08b38428b50..70156c03e3c 100644 --- a/app/views/projects/graphs/show.html.haml +++ b/app/views/projects/graphs/show.html.haml @@ -5,8 +5,6 @@ = webpack_bundle_tag('graphs') = webpack_bundle_tag('graphs_show') -= render 'projects/commits/head' - .js-graphs-show{ class: container_class, 'data-project-graph-path': project_graph_path(@project, current_ref, format: :json) } .sub-header-block .tree-ref-holder diff --git a/app/views/projects/hook_logs/show.html.haml b/app/views/projects/hook_logs/show.html.haml index ab5a7b117d7..1cf4105bd27 100644 --- a/app/views/projects/hook_logs/show.html.haml +++ b/app/views/projects/hook_logs/show.html.haml @@ -1,5 +1,3 @@ -= render 'projects/settings/head' - .row.prepend-top-default.append-bottom-default .col-lg-3 %h4.prepend-top-0 diff --git a/app/views/projects/hooks/edit.html.haml b/app/views/projects/hooks/edit.html.haml index c8c17d2d828..b1219f019d7 100644 --- a/app/views/projects/hooks/edit.html.haml +++ b/app/views/projects/hooks/edit.html.haml @@ -1,5 +1,4 @@ - page_title 'Integrations' -= render 'projects/settings/head' .row.prepend-top-default .col-lg-3 @@ -19,4 +18,3 @@ %hr = render partial: 'projects/hook_logs/index', locals: { hook: @hook, hook_logs: @hook_logs, project: @project } - diff --git a/app/views/projects/issues/_head.html.haml b/app/views/projects/issues/_head.html.haml deleted file mode 100644 index e9f21594a71..00000000000 --- a/app/views/projects/issues/_head.html.haml +++ /dev/null @@ -1,33 +0,0 @@ -= content_for :sub_nav do - .scrolling-tabs-container.sub-nav-scroll - = render 'shared/nav_scroll' - .nav-links.sub-nav.scrolling-tabs - %ul{ class: (container_class) } - - if project_nav_tab?(:issues) && !current_controller?(:merge_requests) - = nav_link(controller: :issues) do - = link_to project_issues_path(@project), title: 'Issues' do - %span - List - - = nav_link(controller: :boards) do - = link_to project_boards_path(@project), title: 'Board' do - %span - Board - - - if project_nav_tab?(:merge_requests) && current_controller?(:merge_requests) - = nav_link(controller: :merge_requests) do - = link_to project_merge_requests_path(@project), title: 'Merge Requests' do - %span - Merge Requests - - - if project_nav_tab? :labels - = nav_link(controller: :labels) do - = link_to project_labels_path(@project), title: 'Labels' do - %span - Labels - - - if project_nav_tab? :milestones - = nav_link(controller: :milestones) do - = link_to project_milestones_path(@project), title: 'Milestones' do - %span - Milestones diff --git a/app/views/projects/issues/_merge_requests.html.haml b/app/views/projects/issues/_merge_requests.html.haml index 6a567487514..5f97d31f610 100644 --- a/app/views/projects/issues/_merge_requests.html.haml +++ b/app/views/projects/issues/_merge_requests.html.haml @@ -2,13 +2,13 @@ %h2.merge-requests-title = pluralize(@merge_requests.count, 'Related Merge Request') %ul.unstyled-list.related-merge-requests - - has_any_ci = @merge_requests.any?(&:head_pipeline) + - has_any_head_pipeline = @merge_requests.any?(&:head_pipeline_id) - @merge_requests.each do |merge_request| %li %span.merge-request-ci-status - if merge_request.head_pipeline = render_pipeline_status(merge_request.head_pipeline) - - elsif has_any_ci + - elsif has_any_head_pipeline = icon('blank fw') %span.merge-request-id = merge_request.to_reference diff --git a/app/views/projects/issues/edit.html.haml b/app/views/projects/issues/edit.html.haml deleted file mode 100644 index 1b7d878c38c..00000000000 --- a/app/views/projects/issues/edit.html.haml +++ /dev/null @@ -1,7 +0,0 @@ -- page_title "Edit", "#{@issue.title} (#{@issue.to_reference})", "Issues" - -%h3.page-title - Edit Issue ##{@issue.iid} -%hr - -= render "form" diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml index e72c94695bc..bfaf024428d 100644 --- a/app/views/projects/issues/index.html.haml +++ b/app/views/projects/issues/index.html.haml @@ -3,8 +3,6 @@ - page_title "Issues" - new_issue_email = @project.new_issue_address(current_user) -= content_for :sub_nav do - = render "projects/issues/head" - content_for :page_specific_javascripts do = webpack_bundle_tag 'common_vue' diff --git a/app/views/projects/jobs/index.html.haml b/app/views/projects/jobs/index.html.haml index 8604c7d3ea4..4a238b99b58 100644 --- a/app/views/projects/jobs/index.html.haml +++ b/app/views/projects/jobs/index.html.haml @@ -1,6 +1,5 @@ - @no_container = true - page_title "Jobs" -= render "projects/pipelines/head" %div{ class: container_class } .top-area diff --git a/app/views/projects/jobs/show.html.haml b/app/views/projects/jobs/show.html.haml index 975c08c06e6..ce0e3872240 100644 --- a/app/views/projects/jobs/show.html.haml +++ b/app/views/projects/jobs/show.html.haml @@ -2,7 +2,6 @@ - add_to_breadcrumbs "Jobs", project_jobs_path(@project) - breadcrumb_title "##{@build.id}" - page_title "#{@build.name} (##{@build.id})", "Jobs" -= render "projects/pipelines/head" %div{ class: container_class } .build-page.js-build-page diff --git a/app/views/projects/labels/edit.html.haml b/app/views/projects/labels/edit.html.haml index 84b0b65d1c0..b8ee4305142 100644 --- a/app/views/projects/labels/edit.html.haml +++ b/app/views/projects/labels/edit.html.haml @@ -1,6 +1,5 @@ - @no_container = true - page_title "Edit", @label.name, "Labels" -= render "shared/mr_head" %div{ class: container_class } %h3.page-title diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml index 10d07ce8e45..80e4dce1a80 100644 --- a/app/views/projects/labels/index.html.haml +++ b/app/views/projects/labels/index.html.haml @@ -3,8 +3,6 @@ - hide_class = '' - can_admin_label = can?(current_user, :admin_label, @project) -= render "shared/mr_head" - - if @labels.exists? || @prioritized_labels.exists? %div{ class: container_class } .top-area.adjust diff --git a/app/views/projects/labels/new.html.haml b/app/views/projects/labels/new.html.haml index 562b6fb8d8c..02f59f30a39 100644 --- a/app/views/projects/labels/new.html.haml +++ b/app/views/projects/labels/new.html.haml @@ -1,7 +1,6 @@ - @no_container = true - breadcrumb_title "Labels" - page_title "New Label" -= render "shared/mr_head" %div{ class: container_class } %h3.page-title diff --git a/app/views/projects/merge_requests/_head.html.haml b/app/views/projects/merge_requests/_head.html.haml deleted file mode 100644 index 1e505222887..00000000000 --- a/app/views/projects/merge_requests/_head.html.haml +++ /dev/null @@ -1,21 +0,0 @@ -= content_for :sub_nav do - .scrolling-tabs-container.sub-nav-scroll - = render 'shared/nav_scroll' - .nav-links.sub-nav.scrolling-tabs - %ul{ class: (container_class) } - = nav_link(controller: :merge_requests) do - = link_to project_merge_requests_path(@project), title: 'Merge Requests' do - %span - List - - - if project_nav_tab? :labels - = nav_link(controller: :labels) do - = link_to project_labels_path(@project), title: 'Labels' do - %span - Labels - - - if project_nav_tab? :milestones - = nav_link(controller: :milestones) do - = link_to project_milestones_path(@project), title: 'Milestones' do - %span - Milestones diff --git a/app/views/projects/merge_requests/_mr_title.html.haml b/app/views/projects/merge_requests/_mr_title.html.haml index f3c44c94a5c..9ff85c2ee4c 100644 --- a/app/views/projects/merge_requests/_mr_title.html.haml +++ b/app/views/projects/merge_requests/_mr_title.html.haml @@ -29,7 +29,7 @@ - unless current_user == @merge_request.author %li= link_to 'Report abuse', new_abuse_report_path(user_id: @merge_request.author.id, ref_url: merge_request_url(@merge_request)) - if can_update_merge_request - %li{ class: merge_request_button_visibility(@merge_request, true) } + %li{ class: [merge_request_button_visibility(@merge_request, true), 'js-close-item'] } = link_to 'Close', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, title: 'Close merge request' %li{ class: merge_request_button_visibility(@merge_request, false) } = link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: 'reopen-mr-link', title: 'Reopen merge request' diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml index 2c53891a92d..6b8dcb3e60b 100644 --- a/app/views/projects/merge_requests/index.html.haml +++ b/app/views/projects/merge_requests/index.html.haml @@ -4,9 +4,6 @@ - new_merge_request_path = project_new_merge_request_path(merge_project) if merge_project - page_title "Merge Requests" -- unless @project.issues_enabled? - = content_for :sub_nav do - = render "projects/merge_requests/head" - content_for :page_specific_javascripts do = webpack_bundle_tag 'common_vue' diff --git a/app/views/projects/milestones/edit.html.haml b/app/views/projects/milestones/edit.html.haml index 1e66c6079e3..af3f25c6a30 100644 --- a/app/views/projects/milestones/edit.html.haml +++ b/app/views/projects/milestones/edit.html.haml @@ -1,6 +1,5 @@ - @no_container = true - page_title "Edit", @milestone.title, "Milestones" -= render "shared/mr_head" %div{ class: container_class } diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml index f3abecdd302..fcbf7cb802b 100644 --- a/app/views/projects/milestones/index.html.haml +++ b/app/views/projects/milestones/index.html.haml @@ -1,8 +1,6 @@ - @no_container = true - page_title 'Milestones' -= render "shared/mr_head" - %div{ class: container_class } .top-area = render 'shared/milestones_filter', counts: milestone_counts(@project.milestones) diff --git a/app/views/projects/milestones/new.html.haml b/app/views/projects/milestones/new.html.haml index 84ffbc0a926..c301f517013 100644 --- a/app/views/projects/milestones/new.html.haml +++ b/app/views/projects/milestones/new.html.haml @@ -1,7 +1,6 @@ - @no_container = true - breadcrumb_title "Milestones" - page_title "New Milestone" -= render "shared/mr_head" %div{ class: container_class } %h3.page-title diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index 1f5f18801ad..a5153df1159 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -3,7 +3,6 @@ - breadcrumb_title @milestone.title - page_title @milestone.title, "Milestones" - page_description @milestone.description -= render "shared/mr_head" %div{ class: container_class } .detail-page-header.milestone-page-header diff --git a/app/views/projects/network/show.html.haml b/app/views/projects/network/show.html.haml index e29cb277389..8a19497c55b 100644 --- a/app/views/projects/network/show.html.haml +++ b/app/views/projects/network/show.html.haml @@ -2,7 +2,6 @@ - page_title "Graph", @ref - content_for :page_specific_javascripts do = page_specific_javascript_bundle_tag('network') -= render "projects/commits/head" = render "head" %div{ class: container_class } .project-network diff --git a/app/views/projects/notes/_actions.html.haml b/app/views/projects/notes/_actions.html.haml index de76832331a..4961835f12a 100644 --- a/app/views/projects/notes/_actions.html.haml +++ b/app/views/projects/notes/_actions.html.haml @@ -1,7 +1,8 @@ +- access = note_max_access_for_user(note) - if note.has_special_role?(Note::SpecialRole::FIRST_TIME_CONTRIBUTOR) - %span.note-role.note-role-special.has-tooltip{ title: _("This is the author's first Merge Request to this project. Handle with care.") } + %span.note-role.note-role-special.has-tooltip{ title: _("This is the author's first Merge Request to this project.") } = issuable_first_contribution_icon -- if access = note_max_access_for_user(note) +- if access.nonzero? %span.note-role.note-role-access= Gitlab::Access.human_access(access) - if note.resolvable? diff --git a/app/views/projects/pages/show.html.haml b/app/views/projects/pages/show.html.haml index 098b0ef56ef..04e647c0dc6 100644 --- a/app/views/projects/pages/show.html.haml +++ b/app/views/projects/pages/show.html.haml @@ -1,5 +1,4 @@ - page_title 'Pages' -= render "projects/settings/head" %h3.page_title Pages diff --git a/app/views/projects/pipeline_schedules/index.html.haml b/app/views/projects/pipeline_schedules/index.html.haml index 2b081786b6a..4fbdd1dd5e4 100644 --- a/app/views/projects/pipeline_schedules/index.html.haml +++ b/app/views/projects/pipeline_schedules/index.html.haml @@ -7,8 +7,6 @@ - @no_container = true - page_title _("Pipeline Schedules") -= render "projects/pipelines/head" - %div{ class: container_class } #pipeline-schedules-callout{ data: { docs_url: help_page_path('user/project/pipelines/schedules') } } .top-area diff --git a/app/views/projects/pipelines/_head.html.haml b/app/views/projects/pipelines/_head.html.haml deleted file mode 100644 index ee2f236cec4..00000000000 --- a/app/views/projects/pipelines/_head.html.haml +++ /dev/null @@ -1,34 +0,0 @@ -= content_for :sub_nav do - .scrolling-tabs-container.sub-nav-scroll - = render 'shared/nav_scroll' - .nav-links.sub-nav.scrolling-tabs - %ul{ class: (container_class) } - - if project_nav_tab? :pipelines - = nav_link(path: ['pipelines#index', 'pipelines#show']) do - = link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do - %span - Pipelines - - - if project_nav_tab? :builds - = nav_link(controller: [:jobs, :artifacts]) do - = link_to project_jobs_path(@project), title: 'Jobs', class: 'shortcuts-builds' do - %span - Jobs - - - if project_nav_tab? :pipelines - = nav_link(controller: :pipeline_schedules) do - = link_to pipeline_schedules_path(@project), title: 'Schedules', class: 'shortcuts-builds' do - %span - Schedules - - - if project_nav_tab? :environments - = nav_link(controller: :environments) do - = link_to project_environments_path(@project), title: 'Environments', class: 'shortcuts-environments' do - %span - Environments - - - if @project.feature_available?(:builds, current_user) && !@project.empty_repo? - = nav_link(path: 'pipelines#charts') do - = link_to charts_project_pipelines_path(@project), title: 'Charts', class: 'shortcuts-pipelines-charts' do - %span - Charts diff --git a/app/views/projects/pipelines/charts.html.haml b/app/views/projects/pipelines/charts.html.haml index 487ac87186d..ba55bc23add 100644 --- a/app/views/projects/pipelines/charts.html.haml +++ b/app/views/projects/pipelines/charts.html.haml @@ -4,7 +4,6 @@ - content_for :page_specific_javascripts do = page_specific_javascript_bundle_tag('common_d3') = page_specific_javascript_bundle_tag('graphs') -= render 'head' %div{ class: container_class } .sub-header-block diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 4f53efcf791..a10a7c23924 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -1,6 +1,5 @@ - @no_container = true - page_title "Pipelines" -= render "projects/pipelines/head" %div{ 'class' => container_class } - if show_auto_devops_callout?(@project) diff --git a/app/views/projects/pipelines/show.html.haml b/app/views/projects/pipelines/show.html.haml index 7cc9fe79afd..2174154b207 100644 --- a/app/views/projects/pipelines/show.html.haml +++ b/app/views/projects/pipelines/show.html.haml @@ -2,7 +2,6 @@ - add_to_breadcrumbs "Pipelines", project_pipelines_path(@project) - breadcrumb_title "##{@pipeline.id}" - page_title "Pipeline" -= render "projects/pipelines/head" .js-pipeline-container{ class: container_class, data: { controller_action: "#{controller.action_name}" } } - if @commit diff --git a/app/views/projects/pipelines_settings/_show.html.haml b/app/views/projects/pipelines_settings/_show.html.haml index 21d01242c0e..77211099830 100644 --- a/app/views/projects/pipelines_settings/_show.html.haml +++ b/app/views/projects/pipelines_settings/_show.html.haml @@ -26,7 +26,8 @@ %strong Disable Auto DevOps %br %span.descr - An explicit <code>.gitlab-ci.yml</code> needs to be specified before you can begin using Continious Integration and Delivery. + An explicit <code>.gitlab-ci.yml</code> needs to be specified before you can begin using Continuous Integration and Delivery. + .radio = form.label :enabled_nil do = form.radio_button :enabled, '' diff --git a/app/views/projects/registry/repositories/_image.html.haml b/app/views/projects/registry/repositories/_image.html.haml deleted file mode 100644 index a0535edafc3..00000000000 --- a/app/views/projects/registry/repositories/_image.html.haml +++ /dev/null @@ -1,32 +0,0 @@ -.container-image.js-toggle-container - .container-image-head - = link_to "#", class: "js-toggle-button" do - = icon('chevron-down', 'aria-hidden': 'true') - = escape_once(image.path) - - = clipboard_button(clipboard_text: "docker pull #{image.location}") - - - if can?(current_user, :update_container_image, @project) - .controls.hidden-xs.pull-right - = link_to project_container_registry_path(@project, image), - class: 'btn btn-remove has-tooltip', - title: 'Remove repository', - data: { confirm: 'Are you sure?' }, - method: :delete do - = icon('trash cred', 'aria-hidden': 'true') - - .container-image-tags.js-toggle-content.hide - - if image.has_tags? - .table-holder - %table.table.tags - %thead - %tr - %th Tag - %th Tag ID - %th Size - %th Created - - if can?(current_user, :update_container_image, @project) - %th - = render partial: 'tag', collection: image.tags - - else - .nothing-here-block No tags in Container Registry for this container image. diff --git a/app/views/projects/registry/repositories/index.html.haml b/app/views/projects/registry/repositories/index.html.haml index 5661af01302..36ea5e013e4 100644 --- a/app/views/projects/registry/repositories/index.html.haml +++ b/app/views/projects/registry/repositories/index.html.haml @@ -1,60 +1,49 @@ - page_title "Container Registry" -.row.prepend-top-default.append-bottom-default - .col-lg-3 - %h4.prepend-top-0 +%section + .settings-header + %h4 = page_title %p - With the Docker Container Registry integrated into GitLab, every project - can have its own space to store its Docker images. + = s_('ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images.') %p.append-bottom-0 = succeed '.' do - Learn more about - = link_to 'Container Registry', help_page_path('user/project/container_registry'), target: '_blank' + = s_('ContainerRegistry|Learn more about') + = link_to _('Container Registry'), help_page_path('user/project/container_registry'), target: '_blank' + .row.registry-placeholder.prepend-bottom-10 + .col-lg-12 + #js-vue-registry-images{ data: { endpoint: project_container_registry_index_path(@project, format: :json) } } - .col-lg-9 - .panel.panel-default - .panel-heading - %h4.panel-title - How to use the Container Registry - .panel-body - %p - First log in to GitLab’s Container Registry using your GitLab username - and password. If you have - = link_to '2FA enabled', help_page_path('user/profile/account/two_factor_authentication'), target: '_blank' - you need to use a - = succeed ':' do - = link_to 'personal access token', help_page_path('user/profile/account/two_factor_authentication', anchor: 'personal-access-tokens'), target: '_blank' - %pre - docker login #{Gitlab.config.registry.host_port} - %br - %p - Once you log in, you’re free to create and upload a container image - using the common - %code build - and - %code push - commands: - %pre - :plain - docker build -t #{escape_once(@project.container_registry_url)} . - docker push #{escape_once(@project.container_registry_url)} + = page_specific_javascript_bundle_tag('common_vue') + = page_specific_javascript_bundle_tag('registry_list') - %hr - %h5.prepend-top-default - Use different image names - %p.light - GitLab supports up to 3 levels of image names. The following - examples of images are valid for your project: - %pre - :plain - #{escape_once(@project.container_registry_url)}:tag - #{escape_once(@project.container_registry_url)}/optional-image-name:tag - #{escape_once(@project.container_registry_url)}/optional-name/optional-image-name:tag - - - if @images.blank? - %p.settings-message.text-center.append-bottom-default - No container images stored for this project. Add one by following the - instructions above. - - else - = render partial: 'image', collection: @images + .row.prepend-top-10 + .col-lg-12 + .panel.panel-default + .panel-heading + %h4.panel-title + = s_('ContainerRegistry|How to use the Container Registry') + .panel-body + %p + - link_token = link_to(_('personal access token'), help_page_path('user/profile/account/two_factor_authentication', anchor: 'personal-access-tokens'), target: '_blank') + - link_2fa = link_to(_('2FA enabled'), help_page_path('user/profile/account/two_factor_authentication'), target: '_blank') + = s_('ContainerRegistry|First log in to GitLab’s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:').html_safe % { link_2fa: link_2fa, link_token: link_token } + %pre + docker login #{Gitlab.config.registry.host_port} + %br + %p + = s_('ContainerRegistry|Once you log in, you’re free to create and upload a container image using the common %{build} and %{push} commands').html_safe % { build: "<code>build</code>".html_safe, push: "<code>push</code>".html_safe } + %pre + :plain + docker build -t #{escape_once(@project.container_registry_url)} . + docker push #{escape_once(@project.container_registry_url)} + %hr + %h5.prepend-top-default + = s_('ContainerRegistry|Use different image names') + %p.light + = s_('ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:') + %pre + :plain + #{escape_once(@project.container_registry_url)}:tag + #{escape_once(@project.container_registry_url)}/optional-image-name:tag + #{escape_once(@project.container_registry_url)}/optional-name/optional-image-name:tag diff --git a/app/views/projects/releases/edit.html.haml b/app/views/projects/releases/edit.html.haml index c786298e341..4d962f9433f 100644 --- a/app/views/projects/releases/edit.html.haml +++ b/app/views/projects/releases/edit.html.haml @@ -2,7 +2,6 @@ - add_to_breadcrumbs "Tags", project_tags_path(@project) - breadcrumb_title @tag.name - page_title "Edit", @tag.name, "Tags" -= render "projects/commits/head" %div{ class: container_class } .sub-header-block.no-bottom-space diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml index b842fd57cf3..c0b1c62e8ef 100644 --- a/app/views/projects/services/_form.html.haml +++ b/app/views/projects/services/_form.html.haml @@ -23,7 +23,7 @@ - disabled_class = 'disabled' - disabled_title = @service.disabled_title - = link_to 'Cancel', project_settings_integrations_path(@project), class: 'btn btn-cancel' + = link_to 'Cancel', project_settings_integrations_path(@project), class: 'btn btn-cancel' - if lookup_context.template_exists?('show', "projects/services/#{@service.to_param}", true) %hr diff --git a/app/views/projects/services/edit.html.haml b/app/views/projects/services/edit.html.haml index 3e2a24a4c32..25770df1c90 100644 --- a/app/views/projects/services/edit.html.haml +++ b/app/views/projects/services/edit.html.haml @@ -2,5 +2,4 @@ - page_title @service.title, "Services" - add_to_breadcrumbs("Settings", edit_project_path(@project)) -= render "projects/settings/head" = render 'form' diff --git a/app/views/projects/settings/_head.html.haml b/app/views/projects/settings/_head.html.haml deleted file mode 100644 index 7d24c6a9122..00000000000 --- a/app/views/projects/settings/_head.html.haml +++ /dev/null @@ -1,30 +0,0 @@ -= content_for :sub_nav do - .scrolling-tabs-container.sub-nav-scroll - = render 'shared/nav_scroll' - .nav-links.sub-nav.scrolling-tabs - %ul{ class: container_class } - - can_edit = can?(current_user, :admin_project, @project) - - if can_edit - = nav_link(controller: :projects) do - = link_to edit_project_path(@project), title: 'General' do - %span - General - - if can_edit - = nav_link(controller: [:integrations, :services, :hooks, :hook_logs]) do - = link_to project_settings_integrations_path(@project), title: 'Integrations' do - %span - Integrations - = nav_link(controller: :repository) do - = link_to project_settings_repository_path(@project), title: 'Repository' do - %span - Repository - - if @project.feature_available?(:builds, current_user) - = nav_link(controller: :ci_cd) do - = link_to project_settings_ci_cd_path(@project), title: 'Pipelines' do - %span - Pipelines - - if @project.pages_available? - = nav_link(controller: :pages) do - = link_to project_pages_path(@project), title: 'Pages' do - %span - Pages diff --git a/app/views/projects/settings/ci_cd/show.html.haml b/app/views/projects/settings/ci_cd/show.html.haml index 47c056d097a..62455d0d40d 100644 --- a/app/views/projects/settings/ci_cd/show.html.haml +++ b/app/views/projects/settings/ci_cd/show.html.haml @@ -2,8 +2,6 @@ - page_title "CI / CD Settings" - page_title "CI / CD" -= render "projects/settings/head" - - expanded = Rails.env.test? %section.settings#js-general-pipeline-settings diff --git a/app/views/projects/settings/integrations/show.html.haml b/app/views/projects/settings/integrations/show.html.haml index 933daa7f549..2f1a548e119 100644 --- a/app/views/projects/settings/integrations/show.html.haml +++ b/app/views/projects/settings/integrations/show.html.haml @@ -1,6 +1,5 @@ - @content_class = "limit-container-width" unless fluid_layout - breadcrumb_title "Integrations Settings" - page_title 'Integrations' -= render "projects/settings/head" = render 'projects/hooks/index' = render 'projects/services/index' diff --git a/app/views/projects/settings/members/show.html.haml b/app/views/projects/settings/members/show.html.haml index 1e7695ac397..ea2cd36b212 100644 --- a/app/views/projects/settings/members/show.html.haml +++ b/app/views/projects/settings/members/show.html.haml @@ -1,6 +1,5 @@ - @content_class = "limit-container-width" unless fluid_layout - page_title "Members" -= render "projects/settings/head" = render "projects/project_members/index" diff --git a/app/views/projects/settings/repository/show.html.haml b/app/views/projects/settings/repository/show.html.haml index 6d4af72b8ea..517d51993d2 100644 --- a/app/views/projects/settings/repository/show.html.haml +++ b/app/views/projects/settings/repository/show.html.haml @@ -2,8 +2,6 @@ - page_title "Repository" - @content_class = "limit-container-width" unless fluid_layout -= render "projects/settings/head" - - content_for :page_specific_javascripts do = page_specific_javascript_bundle_tag('common_vue') = page_specific_javascript_bundle_tag('deploy_keys') diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index d8f5114f4b5..705a4607ad2 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -7,7 +7,6 @@ = render partial: 'flash_messages', locals: { project: @project } -= render "projects/head" = render "projects/last_push" = render "home_panel" diff --git a/app/views/projects/tags/_tag.html.haml b/app/views/projects/tags/_tag.html.haml index 468ab922542..1927216e191 100644 --- a/app/views/projects/tags/_tag.html.haml +++ b/app/views/projects/tags/_tag.html.haml @@ -2,12 +2,11 @@ - release = @releases.find { |release| release.tag == tag.name } %li.flex-row .row-main-content.str-truncated - = link_to project_tag_path(@project, tag.name), class: 'item-title ref-name' do - = icon('tag') - = tag.name + = icon('tag') + = link_to tag.name, project_tag_path(@project, tag.name), class: 'item-title ref-name prepend-left-4' - if protected_tag?(@project, tag) - %span.label.label-success + %span.label.label-success.prepend-left-4 protected - if tag.message.present? diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml index a6fe02fcae0..27d58d4c0e8 100644 --- a/app/views/projects/tags/index.html.haml +++ b/app/views/projects/tags/index.html.haml @@ -2,7 +2,6 @@ - @sort ||= sort_value_recently_updated - page_title "Tags" - add_to_breadcrumbs("Repository", project_tree_path(@project)) -= render "projects/commits/head" .flex-list{ class: container_class } .top-area.adjust diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml index 5d6eb4f4026..43aa2b27af6 100644 --- a/app/views/projects/tags/show.html.haml +++ b/app/views/projects/tags/show.html.haml @@ -2,7 +2,6 @@ - add_to_breadcrumbs "Tags", project_tags_path(@project) - breadcrumb_title @tag.name - page_title @tag.name, "Tags" -= render "projects/commits/head" %div{ class: container_class } .top-area.multi-line diff --git a/app/views/projects/tree/_old_tree_content.html.haml b/app/views/projects/tree/_old_tree_content.html.haml index 820b947804e..6ea78851b8d 100644 --- a/app/views/projects/tree/_old_tree_content.html.haml +++ b/app/views/projects/tree/_old_tree_content.html.haml @@ -6,7 +6,7 @@ %th= s_('ProjectFileTree|Name') %th.hidden-xs .pull-left= _('Last commit') - %th.text-right= _('Last Update') + %th.text-right= _('Last update') - if @path.present? %tr.tree-item %td.tree-item-file-name diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml index 853e2a6e7ec..6cddc38d11a 100644 --- a/app/views/projects/tree/_tree_header.html.haml +++ b/app/views/projects/tree/_tree_header.html.haml @@ -1,10 +1,6 @@ .tree-ref-container .tree-ref-holder = render 'shared/ref_switcher', destination: 'tree', path: @path - - if show_new_repo? - .tree-ref-target-holder.js-tree-ref-target-holder - = icon('long-arrow-right', title: 'to target branch') - = render 'shared/target_switcher', destination: 'tree', path: @path - unless show_new_repo? = render 'projects/tree/old_tree_header' diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml index d84a1fd7ee1..0cc6674842a 100644 --- a/app/views/projects/tree/show.html.haml +++ b/app/views/projects/tree/show.html.haml @@ -11,10 +11,8 @@ = webpack_bundle_tag 'common_vue' = webpack_bundle_tag 'repo' -= render "projects/commits/head" - %div{ class: [container_class, ("limit-container-width" unless fluid_layout)] } - - if show_auto_devops_callout?(@project) + - if show_auto_devops_callout?(@project) && !show_new_repo? = render 'shared/auto_devops_callout' = render 'projects/last_push' = render 'projects/files', commit: @last_commit, project: @project, ref: @ref, content_url: project_tree_path(@project, @id) diff --git a/app/views/projects/wikis/_form.html.haml b/app/views/projects/wikis/_form.html.haml index e5a1fccf9ba..4e265bf733a 100644 --- a/app/views/projects/wikis/_form.html.haml +++ b/app/views/projects/wikis/_form.html.haml @@ -1,4 +1,5 @@ -- commit_message = @page.persisted? ? "Update #{@page.title}" : "Create #{@page.title}" +- commit_message = @page.persisted? ? s_("WikiPageEdit|Update %{page_title}") : s_("WikiPageCreate|Create %{page_title}") +- commit_message = commit_message % { page_title: @page.title } = form_for [@project.namespace.becomes(Namespace), @project, @page], method: @page.persisted? ? :put : :post, html: { class: 'form-horizontal wiki-form common-note-form prepend-top-default js-quick-submit' } do |f| = form_errors(@page) @@ -12,13 +13,13 @@ .form-group .col-sm-12= f.label :format, class: 'control-label-full-width' .col-sm-12 - = f.select :format, options_for_select(ProjectWiki::MARKUPS, {selected: @page.format}), {}, class: "form-control" + = f.select :format, options_for_select(ProjectWiki::MARKUPS, {selected: @page.format}), {}, class: 'form-control' .form-group .col-sm-12= f.label :content, class: 'control-label-full-width' .col-sm-12 = render layout: 'projects/md_preview', locals: { url: project_wiki_preview_markdown_path(@project, @page.slug) } do - = render 'projects/zen', f: f, attr: :content, classes: 'note-textarea', placeholder: 'Write your content or drag files here...' + = render 'projects/zen', f: f, attr: :content, classes: 'note-textarea', placeholder: s_("WikiPage|Write your content or drag files here...") = render 'shared/notes/hints' .clearfix @@ -26,12 +27,11 @@ .help-block = succeed '.' do - To link to a (new) page, simply type - %code [Link Title](page-slug) + = (s_("WikiMarkdownTip|To link to a (new) page, simply type %{link_example}") % { link_example: '<code>[Link Title](page-slug)</code>' }).html_safe = succeed '.' do - More examples are in the - = link_to 'documentation', help_page_path("user/markdown", anchor: "wiki-specific-markdown") + - markdown_link = link_to s_("WikiMarkdownDocs|documentation"), help_page_path('user/markdown', anchor: 'wiki-specific-markdown') + = (s_("WikiMarkdownDocs|More examples are in the %{docs_link}") % { docs_link: markdown_link }).html_safe .form-group .col-sm-12= f.label :commit_message, class: 'control-label-full-width' @@ -39,10 +39,10 @@ .form-actions - if @page && @page.persisted? - = f.submit 'Save changes', class: "btn-save btn" + = f.submit _("Save changes"), class: 'btn-save btn' .pull-right - = link_to "Cancel", project_wiki_path(@project, @page), class: "btn btn-cancel btn-grouped" + = link_to _("Cancel"), project_wiki_path(@project, @page), class: 'btn btn-cancel btn-grouped' - else - = f.submit 'Create page', class: "btn-create btn" + = f.submit s_("Wiki|Create page"), class: 'btn-create btn' .pull-right - = link_to "Cancel", project_wiki_path(@project, :home), class: "btn btn-cancel" + = link_to _("Cancel"), project_wiki_path(@project, :home), class: 'btn btn-cancel' diff --git a/app/views/projects/wikis/_main_links.html.haml b/app/views/projects/wikis/_main_links.html.haml index 3bbd8042c3a..cadda0a33c2 100644 --- a/app/views/projects/wikis/_main_links.html.haml +++ b/app/views/projects/wikis/_main_links.html.haml @@ -1,9 +1,9 @@ - if (@page && @page.persisted?) - if can?(current_user, :create_wiki, @project) = link_to '#modal-new-wiki', class: "add-new-wiki btn btn-new", "data-toggle" => "modal" do - New page + = s_("Wiki|New page") = link_to project_wiki_history_path(@project, @page), class: "btn" do - Page history + = s_("Wiki|Page history") - if can?(current_user, :create_wiki, @project) && @page.latest? = link_to project_wiki_edit_path(@project, @page), class: "btn js-wiki-edit" do - Edit + = _("Edit") diff --git a/app/views/projects/wikis/_new.html.haml b/app/views/projects/wikis/_new.html.haml index 13dd8461433..06a3cac12d5 100644 --- a/app/views/projects/wikis/_new.html.haml +++ b/app/views/projects/wikis/_new.html.haml @@ -3,16 +3,15 @@ .modal-content .modal-header %a.close{ href: "#", "data-dismiss" => "modal" } × - %h3.page-title New Wiki Page + %h3.page-title= s_("WikiNewPageTitle|New Wiki Page") .modal-body %form.new-wiki-page .form-group = label_tag :new_wiki_path do - %span Page slug - = text_field_tag :new_wiki_path, nil, placeholder: 'how-to-setup', class: 'form-control', required: true, :'data-wikis-path' => project_wikis_path(@project), autofocus: true + %span= s_("WikiPage|Page slug") + = text_field_tag :new_wiki_path, nil, placeholder: s_("WikiNewPagePlaceholder|how-to-setup"), class: 'form-control', required: true, :'data-wikis-path' => project_wikis_path(@project), autofocus: true %span.new-wiki-page-slug-tip = icon('lightbulb-o') - Tip: You can specify the full path for the new file. - We will automatically create any missing directories. + = s_("WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories.") .form-actions - = button_tag 'Create page', class: 'build-new-wiki btn btn-create' + = button_tag s_("Wiki|Create page"), class: "build-new-wiki btn btn-create" diff --git a/app/views/projects/wikis/_pages_wiki_page.html.haml b/app/views/projects/wikis/_pages_wiki_page.html.haml index 7c2f562d422..0a1ccbc5f1c 100644 --- a/app/views/projects/wikis/_pages_wiki_page.html.haml +++ b/app/views/projects/wikis/_pages_wiki_page.html.haml @@ -2,4 +2,4 @@ = link_to wiki_page.title, project_wiki_path(@project, wiki_page) %small (#{wiki_page.format}) .pull-right - %small Last edited #{time_ago_with_tooltip(wiki_page.commit.authored_date)} + %small= (s_("Last edited %{date}") % { date: time_ago_with_tooltip(wiki_page.commit.authored_date) }).html_safe diff --git a/app/views/projects/wikis/_sidebar.html.haml b/app/views/projects/wikis/_sidebar.html.haml index f7283ae4739..5b781294d68 100644 --- a/app/views/projects/wikis/_sidebar.html.haml +++ b/app/views/projects/wikis/_sidebar.html.haml @@ -8,7 +8,7 @@ = link_to git_access_url, class: active_nav_link?(path: 'wikis#git_access') ? 'active' : '' do = succeed ' ' do = icon('cloud-download') - Clone repository + = _("Clone repository") .blocks-container .block.block-first @@ -17,6 +17,6 @@ .block = link_to project_wikis_pages_path(@project), class: 'btn btn-block' do - More Pages + = s_("Wiki|More Pages") = render 'projects/wikis/new' diff --git a/app/views/projects/wikis/edit.html.haml b/app/views/projects/wikis/edit.html.haml index 8fd60216536..0d77e5bd16d 100644 --- a/app/views/projects/wikis/edit.html.haml +++ b/app/views/projects/wikis/edit.html.haml @@ -1,11 +1,10 @@ - @content_class = "limit-container-width limit-container-width-sm" unless fluid_layout -- page_title "Edit", @page.title.capitalize, "Wiki" +- page_title _("Edit"), @page.title.capitalize, _("Wiki") - if @conflict .alert.alert-danger - Someone edited the page the same time you did. Please check out - = link_to "the page", project_wiki_path(@project, @page), target: "_blank" - and make sure your changes will not unintentionally remove theirs. + - page_link = link_to s_("WikiPageConflictMessage|the page"), project_wiki_path(@project, @page), target: "_blank" + = (s_("WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{page_link} and make sure your changes will not unintentionally remove theirs.") % { page_link: page_link }).html_safe .wiki-page-header.has-sidebar-toggle %button.btn.btn-default.sidebar-toggle.js-sidebar-wiki-toggle{ role: "button", type: "button" } @@ -20,20 +19,20 @@ %span.light · - if @page.persisted? - Edit Page + = s_("Wiki|Edit Page") - else - Create Page + = s_("Wiki|Create Page") .nav-controls - if can?(current_user, :create_wiki, @project) = link_to '#modal-new-wiki', class: "add-new-wiki btn btn-new", "data-toggle" => "modal" do - New page + = s_("Wiki|New page") - if @page.persisted? = link_to project_wiki_history_path(@project, @page), class: "btn" do - Page history + = s_("Wiki|Page history") - if can?(current_user, :admin_wiki, @project) - = link_to project_wiki_path(@project, @page), data: { confirm: "Are you sure you want to delete this page?"}, method: :delete, class: "btn btn-danger" do - Delete + = link_to project_wiki_path(@project, @page), data: { confirm: s_("WikiPageConfirmDelete|Are you sure you want to delete this page?")}, method: :delete, class: "btn btn-danger" do + = _("Delete") = render 'form' diff --git a/app/views/projects/wikis/empty.html.haml b/app/views/projects/wikis/empty.html.haml index 7dfa405d063..911e1339541 100644 --- a/app/views/projects/wikis/empty.html.haml +++ b/app/views/projects/wikis/empty.html.haml @@ -1,6 +1,6 @@ -- page_title "Wiki" +- page_title _("Wiki") -%h3.page-title Empty page +%h3.page-title= _("Wiki|Empty page") %hr .error_message - You are not allowed to create wiki pages + = s_("WikiEmptyPageError|You are not allowed to create wiki pages") diff --git a/app/views/projects/wikis/git_access.html.haml b/app/views/projects/wikis/git_access.html.haml index e740fb93ea4..10dbbc0e42c 100644 --- a/app/views/projects/wikis/git_access.html.haml +++ b/app/views/projects/wikis/git_access.html.haml @@ -1,36 +1,34 @@ - @content_class = "limit-container-width limit-container-width-sm" unless fluid_layout -- page_title "Git Access", "Wiki" +- page_title s_("WikiClone|Git Access"), _("Wiki") .wiki-page-header.has-sidebar-toggle %button.btn.btn-default.visible-xs.visible-sm.pull-right.sidebar-toggle.js-sidebar-wiki-toggle{ role: "button", type: "button" } = icon('angle-double-left') .git-access-header - Clone repository + = _("Clone repository") %strong= @project_wiki.full_path = render "shared/clone_panel", project: @project_wiki .wiki-git-access - %h3 Install Gollum + %h3= s_("WikiClone|Install Gollum") %pre.dark :preserve gem install gollum %p - It is recommended to install - %code github-markdown - so that GFM features render locally: + = (s_("WikiClone|It is recommended to install %{markdown} so that GFM features render locally:") % { markdown: "<code>github-markdown</code>" }).html_safe %pre.dark :preserve gem install github-markdown - %h3 Clone your wiki + %h3= s_("WikiClone|Clone your wiki") %pre.dark :preserve git clone #{ content_tag(:span, h(default_url_to_repo(@project_wiki)), class: 'clone')} cd #{h @project_wiki.path} - %h3 Start Gollum and edit locally + %h3= s_("WikiClone|Start Gollum and edit locally") %pre.dark :preserve gollum diff --git a/app/views/projects/wikis/history.html.haml b/app/views/projects/wikis/history.html.haml index 306feeff259..9ee09262324 100644 --- a/app/views/projects/wikis/history.html.haml +++ b/app/views/projects/wikis/history.html.haml @@ -1,4 +1,4 @@ -- page_title "History", @page.title.capitalize, "Wiki" +- page_title _("History"), @page.title.capitalize, _("Wiki") .wiki-page-header.has-sidebar-toggle %button.btn.btn-default.sidebar-toggle.js-sidebar-wiki-toggle{ role: "button", type: "button" } @@ -9,17 +9,17 @@ = link_to @page.title.capitalize, project_wiki_path(@project, @page) %span.light · - History + = _("History") .table-holder %table.table %thead %tr - %th Page version - %th Author - %th Commit Message - %th Last updated - %th Format + %th= s_("Wiki|Page version") + %th= _("Author") + %th= _("Commit Message") + %th= _("Last updated") + %th= _("Format") %tbody - @page.versions.each_with_index do |version, index| - commit = version @@ -29,13 +29,13 @@ commit.id, index == 0) do = truncate_sha(commit.id) %td - = commit.author.name + = commit.author_name %td = commit.message %td #{time_ago_with_tooltip(version.authored_date)} %td %strong - = @page.page.wiki.page(@page.page.name, commit.id).try(:format) + = version.format = render 'sidebar' diff --git a/app/views/projects/wikis/pages.html.haml b/app/views/projects/wikis/pages.html.haml index d533c611a38..aeef64fd7eb 100644 --- a/app/views/projects/wikis/pages.html.haml +++ b/app/views/projects/wikis/pages.html.haml @@ -1,19 +1,19 @@ - @no_container = true - add_to_breadcrumbs "Wiki", get_project_wiki_path(@project) -- breadcrumb_title "Pages" -- page_title "Pages", "Wiki" +- breadcrumb_title s_("Wiki|Pages") +- page_title s_("Wiki|Pages"), _("Wiki") %div{ class: container_class } .wiki-page-header .nav-text %h2.wiki-page-title - Wiki Pages + = s_("Wiki|Wiki Pages") .nav-controls = link_to project_wikis_git_access_path(@project), class: 'btn' do = icon('cloud-download') - Clone repository + = _("Clone repository") %ul.wiki-pages-list.content-list = render @wiki_entries, context: 'pages' diff --git a/app/views/projects/wikis/show.html.haml b/app/views/projects/wikis/show.html.haml index b066a812ec8..de15fc99eda 100644 --- a/app/views/projects/wikis/show.html.haml +++ b/app/views/projects/wikis/show.html.haml @@ -1,8 +1,8 @@ - @content_class = "limit-container-width limit-container-width-sm" unless fluid_layout - breadcrumb_title @page.title.capitalize - wiki_breadcrumb_dropdown_links(@page.slug) -- page_title @page.title.capitalize, "Wiki" -- add_to_breadcrumbs "Wiki", get_project_wiki_path(@project) +- page_title @page.title.capitalize, _("Wiki") +- add_to_breadcrumbs _("Wiki"), get_project_wiki_path(@project) .wiki-page-header.has-sidebar-toggle %button.btn.btn-default.sidebar-toggle.js-sidebar-wiki-toggle{ role: "button", type: "button" } @@ -11,9 +11,7 @@ .nav-text %h2.wiki-page-title= @page.title.capitalize %span.wiki-last-edit-by - Last edited by - %strong - #{@page.commit.author.name} + = (_("Last edited by %{name}") % { name: "<strong>#{@page.commit.author_name}</strong>" }).html_safe #{time_ago_with_tooltip(@page.commit.authored_date)} .nav-controls @@ -21,8 +19,10 @@ - if @page.historical? .warning_message - This is an old version of this page. - You can view the #{link_to "most recent version", project_wiki_path(@project, @page)} or browse the #{link_to "history", project_wiki_history_path(@project, @page)}. + = s_("WikiHistoricalPage|This is an old version of this page.") + - most_recent_link = link_to s_("WikiHistoricalPage|most recent version"), project_wiki_path(@project, @page) + - history_link = link_to s_("WikiHistoricalPage|history"), project_wiki_history_path(@project, @page) + = (s_("WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}.") % { most_recent_link: most_recent_link, history_link: history_link }).html_safe .wiki-holder.prepend-top-default.append-bottom-default .wiki diff --git a/app/views/shared/_auto_devops_callout.html.haml b/app/views/shared/_auto_devops_callout.html.haml index 2f09c2fec87..7c633175a06 100644 --- a/app/views/shared/_auto_devops_callout.html.haml +++ b/app/views/shared/_auto_devops_callout.html.haml @@ -6,10 +6,10 @@ .svg-container = custom_icon('icon_autodevops') .user-callout-copy - %h4= _('Auto DevOps (Beta)') - %p= _('Auto DevOps can be activated for this project. It will automatically build, test, and deploy your application based on a predefined CI/CD configuration.') + %h4= s_('AutoDevOps|Auto DevOps (Beta)') + %p= s_('AutoDevOps|Auto DevOps can be activated for this project. It will automatically build, test, and deploy your application based on a predefined CI/CD configuration.') %p - #{s_('AutoDevOps|Learn more in the')} - = link_to _('Auto DevOps documentation'), help_page_path('topics/autodevops/index.md'), target: '_blank', rel: 'noopener noreferrer' + - link = link_to(s_('AutoDevOps|Auto DevOps documentation'), help_page_path('topics/autodevops/index.md'), target: '_blank', rel: 'noopener noreferrer') + = s_('AutoDevOps|Learn more in the %{link_to_documentation}').html_safe % { link_to_documentation: link } - = link_to _('Enable in settings'), project_settings_ci_cd_path(@project, anchor: 'js-general-pipeline-settings'), class: 'btn btn-primary js-close-callout' + = link_to s_('AutoDevOps|Enable in settings'), project_settings_ci_cd_path(@project, anchor: 'js-general-pipeline-settings'), class: 'btn btn-primary js-close-callout' diff --git a/app/views/shared/_mr_head.html.haml b/app/views/shared/_mr_head.html.haml deleted file mode 100644 index e7355ae2eea..00000000000 --- a/app/views/shared/_mr_head.html.haml +++ /dev/null @@ -1,4 +0,0 @@ -- if @project.issues_enabled? - = render "projects/issues/head" -- else - = render "projects/merge_requests/head" diff --git a/app/views/shared/_nav_scroll.html.haml b/app/views/shared/_nav_scroll.html.haml deleted file mode 100644 index 61646f150c1..00000000000 --- a/app/views/shared/_nav_scroll.html.haml +++ /dev/null @@ -1,4 +0,0 @@ -.fade-left - = icon('angle-left') -.fade-right - = icon('angle-right') diff --git a/app/views/shared/_personal_access_tokens_form.html.haml b/app/views/shared/_personal_access_tokens_form.html.haml index e415ec64c38..b8b1f4ca42f 100644 --- a/app/views/shared/_personal_access_tokens_form.html.haml +++ b/app/views/shared/_personal_access_tokens_form.html.haml @@ -1,9 +1,9 @@ - type = impersonation ? "impersonation" : "personal access" %h5.prepend-top-0 - Add a #{type} Token + Add a #{type} token %p.profile-settings-content - Pick a name for the application, and we'll give you a unique #{type} Token. + Pick a name for the application, and we'll give you a unique #{type} token. = form_for token, url: path, method: :post, html: { class: 'js-requires-input' } do |f| diff --git a/app/views/shared/_sidebar_toggle_button.html.haml b/app/views/shared/_sidebar_toggle_button.html.haml index eb5ddb0dde4..2530db986e0 100644 --- a/app/views/shared/_sidebar_toggle_button.html.haml +++ b/app/views/shared/_sidebar_toggle_button.html.haml @@ -1,8 +1,8 @@ %a.toggle-sidebar-button.js-toggle-sidebar{ role: "button", type: "button", title: "Toggle sidebar" } - = icon('angle-double-left') - = icon('angle-double-right') + = sprite_icon('angle-double-left', css_class: 'icon-angle-double-left') + = sprite_icon('angle-double-right', css_class: 'icon-angle-double-right') %span.collapse-text Collapse sidebar = button_tag class: 'close-nav-button', type: 'button' do - = icon ('times') + = sprite_icon('close', size: 16) %span.collapse-text Close sidebar diff --git a/app/views/shared/_sort_dropdown.html.haml b/app/views/shared/_sort_dropdown.html.haml index 785a500e44e..7ff5e679f17 100644 --- a/app/views/shared/_sort_dropdown.html.haml +++ b/app/views/shared/_sort_dropdown.html.haml @@ -1,36 +1,16 @@ +- sorted_by = sort_options_hash[@sort] - viewing_issues = controller.controller_name == 'issues' || controller.action_name == 'issues' .dropdown.inline.prepend-left-10 - %button.dropdown-toggle{ type: 'button', data: {toggle: 'dropdown' } } - - if @sort.present? - = sort_options_hash[@sort] - - else - = sort_title_recently_created + %button.dropdown-toggle{ type: 'button', data: { toggle: 'dropdown' } } + = sorted_by = icon('chevron-down') - %ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-sort + %ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-selectable.dropdown-menu-sort %li - = link_to page_filter_path(sort: sort_value_priority, label: true) do - = sort_title_priority - = link_to page_filter_path(sort: sort_value_label_priority, label: true) do - = sort_title_label_priority - = link_to page_filter_path(sort: sort_value_recently_created, label: true) do - = sort_title_recently_created - = link_to page_filter_path(sort: sort_value_oldest_created, label: true) do - = sort_title_oldest_created - = link_to page_filter_path(sort: sort_value_recently_updated, label: true) do - = sort_title_recently_updated - = link_to page_filter_path(sort: sort_value_oldest_updated, label: true) do - = sort_title_oldest_updated - = link_to page_filter_path(sort: sort_value_milestone_soon, label: true) do - = sort_title_milestone_soon - = link_to page_filter_path(sort: sort_value_milestone_later, label: true) do - = sort_title_milestone_later - - if viewing_issues - = link_to page_filter_path(sort: sort_value_due_date_soon, label: true) do - = sort_title_due_date_soon - = link_to page_filter_path(sort: sort_value_due_date_later, label: true) do - = sort_title_due_date_later - = link_to page_filter_path(sort: sort_value_upvotes, label: true) do - = sort_title_upvotes - = link_to page_filter_path(sort: sort_value_downvotes, label: true) do - = sort_title_downvotes + = sortable_item(sort_title_priority, page_filter_path(sort: sort_value_priority, label: true), sorted_by) + = sortable_item(sort_title_created_date, page_filter_path(sort: sort_value_created_date, label: true), sorted_by) + = sortable_item(sort_title_recently_updated, page_filter_path(sort: sort_value_recently_updated, label: true), sorted_by) + = sortable_item(sort_title_milestone, page_filter_path(sort: sort_value_milestone, label: true), sorted_by) + = sortable_item(sort_title_due_date, page_filter_path(sort: sort_value_due_date, label: true), sorted_by) if viewing_issues + = sortable_item(sort_title_popularity, page_filter_path(sort: sort_value_popularity, label: true), sorted_by) + = sortable_item(sort_title_label_priority, page_filter_path(sort: sort_value_label_priority, label: true), sorted_by) diff --git a/app/views/shared/_target_switcher.html.haml b/app/views/shared/_target_switcher.html.haml deleted file mode 100644 index bbe9692a7da..00000000000 --- a/app/views/shared/_target_switcher.html.haml +++ /dev/null @@ -1,16 +0,0 @@ -- dropdown_toggle_text = @ref || @project.default_branch -= form_tag nil, method: :get, class: "project-refs-form project-refs-target-form" do - = hidden_field_tag :destination, destination - - if defined?(path) - = hidden_field_tag :path, path - - @options && @options.each do |key, value| - = hidden_field_tag key, value, id: nil - .dropdown - = dropdown_toggle dropdown_toggle_text, { toggle: "dropdown", selected: dropdown_toggle_text, ref: @ref, refs_url: refs_project_path(@project, find: ['branches']), field_name: 'ref', input_field_name: 'new-branch', submit_form_on_click: true, visit: false }, { toggle_class: "js-project-refs-dropdown" } - .dropdown-menu.dropdown-menu-selectable.git-revision-dropdown{ class: ("dropdown-menu-align-right" if local_assigns[:align_right]) } - = dropdown_title _("Create a new branch") - = dropdown_input _("Create a new branch") - = dropdown_title _("Select existing branch"), options: {close: false} - = dropdown_filter _("Search branches and tags") - = dropdown_content - = dropdown_loading diff --git a/app/views/shared/boards/_show.html.haml b/app/views/shared/boards/_show.html.haml index 722890a01e5..ee8ad8e3999 100644 --- a/app/views/shared/boards/_show.html.haml +++ b/app/views/shared/boards/_show.html.haml @@ -12,13 +12,11 @@ %script#js-board-template{ type: "text/x-template" }= render "shared/boards/components/board" %script#js-board-modal-filter{ type: "text/x-template" }= render "shared/issuable/search_bar", type: :boards_modal -= render "projects/issues/head" +#board-app.boards-app{ "v-cloak" => true, data: board_data, ":class" => "{ 'is-compact': detailIssueVisible }" } + .hidden-xs.hidden-sm + = render 'shared/issuable/search_bar', type: :boards -.hidden-xs.hidden-sm - = render 'shared/issuable/search_bar', type: :boards - -#board-app.boards-app{ "v-cloak" => true, data: board_data } - .boards-list{ ":class" => "{ 'is-compact': detailIssueVisible }" } + .boards-list .boards-app-loading.text-center{ "v-if" => "loading" } = icon("spinner spin") %board{ "v-cloak" => true, diff --git a/app/views/shared/icons/_icon_status_canceled.svg b/app/views/shared/icons/_icon_status_canceled.svg index bd5d04e1cd7..bd5d04e1cd7 100755..100644 --- a/app/views/shared/icons/_icon_status_canceled.svg +++ b/app/views/shared/icons/_icon_status_canceled.svg diff --git a/app/views/shared/icons/_icon_status_created.svg b/app/views/shared/icons/_icon_status_created.svg index 326ad04e017..326ad04e017 100755..100644 --- a/app/views/shared/icons/_icon_status_created.svg +++ b/app/views/shared/icons/_icon_status_created.svg diff --git a/app/views/shared/icons/_icon_status_failed.svg b/app/views/shared/icons/_icon_status_failed.svg index 64da5aa31fc..64da5aa31fc 100755..100644 --- a/app/views/shared/icons/_icon_status_failed.svg +++ b/app/views/shared/icons/_icon_status_failed.svg diff --git a/app/views/shared/icons/_icon_status_manual.svg b/app/views/shared/icons/_icon_status_manual.svg index c98839f51a9..c98839f51a9 100755..100644 --- a/app/views/shared/icons/_icon_status_manual.svg +++ b/app/views/shared/icons/_icon_status_manual.svg diff --git a/app/views/shared/icons/_icon_status_pending.svg b/app/views/shared/icons/_icon_status_pending.svg index 02d5da407e3..02d5da407e3 100755..100644 --- a/app/views/shared/icons/_icon_status_pending.svg +++ b/app/views/shared/icons/_icon_status_pending.svg diff --git a/app/views/shared/icons/_icon_status_running.svg b/app/views/shared/icons/_icon_status_running.svg index 532f4fee33c..532f4fee33c 100755..100644 --- a/app/views/shared/icons/_icon_status_running.svg +++ b/app/views/shared/icons/_icon_status_running.svg diff --git a/app/views/shared/icons/_icon_status_skipped.svg b/app/views/shared/icons/_icon_status_skipped.svg index a9ba29c922c..a9ba29c922c 100755..100644 --- a/app/views/shared/icons/_icon_status_skipped.svg +++ b/app/views/shared/icons/_icon_status_skipped.svg diff --git a/app/views/shared/icons/_icon_status_success.svg b/app/views/shared/icons/_icon_status_success.svg index eed5006bebe..eed5006bebe 100755..100644 --- a/app/views/shared/icons/_icon_status_success.svg +++ b/app/views/shared/icons/_icon_status_success.svg diff --git a/app/views/shared/icons/_icon_status_warning.svg b/app/views/shared/icons/_icon_status_warning.svg index cb785635b7e..cb785635b7e 100755..100644 --- a/app/views/shared/icons/_icon_status_warning.svg +++ b/app/views/shared/icons/_icon_status_warning.svg diff --git a/app/views/shared/issuable/_close_reopen_button.html.haml b/app/views/shared/issuable/_close_reopen_button.html.haml index f16bc8dd430..9ef015047c9 100644 --- a/app/views/shared/issuable/_close_reopen_button.html.haml +++ b/app/views/shared/issuable/_close_reopen_button.html.haml @@ -3,9 +3,9 @@ - button_method = issuable_close_reopen_button_method(issuable) - if can_update && is_current_user - = link_to "Close #{display_issuable_type}", close_issuable_url(issuable), method: button_method, + = link_to "Close #{display_issuable_type}", close_issuable_path(issuable), method: button_method, class: "hidden-xs hidden-sm btn btn-grouped btn-close js-btn-issue-action #{issuable_button_visibility(issuable, true)}", title: "Close #{display_issuable_type}" - = link_to "Reopen #{display_issuable_type}", reopen_issuable_url(issuable), method: button_method, + = link_to "Reopen #{display_issuable_type}", reopen_issuable_path(issuable), method: button_method, class: "hidden-xs hidden-sm btn btn-grouped btn-reopen js-btn-issue-action #{issuable_button_visibility(issuable, false)}", title: "Reopen #{display_issuable_type}" - elsif can_update && !is_current_user = render 'shared/issuable/close_reopen_report_toggle', issuable: issuable diff --git a/app/views/shared/issuable/_close_reopen_report_toggle.html.haml b/app/views/shared/issuable/_close_reopen_report_toggle.html.haml index a38cd319e3c..39a5171c1d6 100644 --- a/app/views/shared/issuable/_close_reopen_report_toggle.html.haml +++ b/app/views/shared/issuable/_close_reopen_report_toggle.html.haml @@ -7,7 +7,7 @@ - button_method = issuable_close_reopen_button_method(issuable) .pull-left.btn-group.prepend-left-10.issuable-close-dropdown.droplab-dropdown.js-issuable-close-dropdown - = link_to "#{display_button_action} #{display_issuable_type}", close_reopen_issuable_url(issuable), + = link_to "#{display_button_action} #{display_issuable_type}", close_reopen_issuable_path(issuable), method: button_method, class: "#{button_class} btn-#{button_action}", title: "#{display_button_action} #{display_issuable_type}" = button_tag type: 'button', class: "#{toggle_class} btn-#{button_action}-color", @@ -16,7 +16,7 @@ %ul#issuable-close-menu.js-issuable-close-menu.dropdown-menu{ class: button_responsive_class, data: { dropdown: true } } %li.close-item{ class: "#{issuable_button_visibility(issuable, true) || 'droplab-item-selected'}", - data: { text: "Close #{display_issuable_type}", url: close_issuable_url(issuable), + data: { text: "Close #{display_issuable_type}", url: close_issuable_path(issuable), button_class: "#{button_class} btn-close", toggle_class: "#{toggle_class} btn-close-color", method: button_method } } %button.btn.btn-transparent = icon('check', class: 'icon') @@ -26,7 +26,7 @@ = display_issuable_type %li.reopen-item{ class: "#{issuable_button_visibility(issuable, false) || 'droplab-item-selected'}", - data: { text: "Reopen #{display_issuable_type}", url: reopen_issuable_url(issuable), + data: { text: "Reopen #{display_issuable_type}", url: reopen_issuable_path(issuable), button_class: "#{button_class} btn-reopen", toggle_class: "#{toggle_class} btn-reopen-color", method: button_method } } %button.btn.btn-transparent = icon('check', class: 'icon') diff --git a/app/views/shared/issuable/_participants.html.haml b/app/views/shared/issuable/_participants.html.haml index 8a71819aa8e..d2b62557e03 100644 --- a/app/views/shared/issuable/_participants.html.haml +++ b/app/views/shared/issuable/_participants.html.haml @@ -11,7 +11,7 @@ .hide-collapsed.participants-list - participants.each do |participant| .participants-author.js-participants-author - = link_to_member(@project, participant, name: false, size: 24) + = link_to_member(@project, participant, name: false, size: 24, lazy_load: true) - if participants_extra > 0 .hide-collapsed.participants-more %a.js-participants-more{ href: "#", data: { original_text: "+ #{participants_size - 7} more", less_text: "- show less" } } diff --git a/app/views/shared/issuable/_user_dropdown_item.html.haml b/app/views/shared/issuable/_user_dropdown_item.html.haml index 48d04678d47..4a3547e9e70 100644 --- a/app/views/shared/issuable/_user_dropdown_item.html.haml +++ b/app/views/shared/issuable/_user_dropdown_item.html.haml @@ -4,7 +4,7 @@ %li.filter-dropdown-item{ class: ('js-current-user' if user == current_user) } %button.btn.btn-link.dropdown-user{ type: :button } .avatar-container.s40 - = user_avatar_without_link(user: user, lazy: avatar[:lazy], url: avatar[:url], size: 40, has_tooltip: false).gsub('/images/{{avatar_url}}','{{avatar_url}}').html_safe + = user_avatar_without_link(user: user, lazy: avatar[:lazy], url: avatar[:url], size: 40, has_tooltip: false) .dropdown-user-details %span = user.name diff --git a/app/views/shared/notes/_comment_button.html.haml b/app/views/shared/notes/_comment_button.html.haml index 1dfe380db16..4b9af78bc1a 100644 --- a/app/views/shared/notes/_comment_button.html.haml +++ b/app/views/shared/notes/_comment_button.html.haml @@ -7,7 +7,7 @@ = button_tag type: 'button', class: 'btn btn-nr dropdown-toggle comment-btn js-note-new-discussion js-disable-on-submit', data: { 'dropdown-trigger' => '#resolvable-comment-menu' }, 'aria-label' => 'Open comment type dropdown' do = icon('caret-down', class: 'toggle-icon') - %ul#resolvable-comment-menu.dropdown-menu{ data: { dropdown: true } } + %ul#resolvable-comment-menu.dropdown-menu.dropdown-open-top{ data: { dropdown: true } } %li#comment.droplab-item-selected{ data: { value: '', 'submit-text' => 'Comment', 'close-text' => "Comment & close #{noteable_name}", 'reopen-text' => "Comment & reopen #{noteable_name}" } } %button.btn.btn-transparent = icon('check', class: 'icon') diff --git a/app/workers/project_migrate_hashed_storage_worker.rb b/app/workers/project_migrate_hashed_storage_worker.rb new file mode 100644 index 00000000000..ca276d7801c --- /dev/null +++ b/app/workers/project_migrate_hashed_storage_worker.rb @@ -0,0 +1,11 @@ +class ProjectMigrateHashedStorageWorker + include Sidekiq::Worker + include DedicatedSidekiqQueue + + def perform(project_id) + project = Project.find_by(id: project_id) + return if project.nil? || project.pending_delete? + + ::Projects::HashedStorageMigrationService.new(project, logger).execute + end +end diff --git a/app/workers/storage_migrator_worker.rb b/app/workers/storage_migrator_worker.rb new file mode 100644 index 00000000000..b48ead799b9 --- /dev/null +++ b/app/workers/storage_migrator_worker.rb @@ -0,0 +1,30 @@ +class StorageMigratorWorker + include Sidekiq::Worker + include DedicatedSidekiqQueue + + BATCH_SIZE = 100 + + def perform(start, finish) + projects = build_relation(start, finish) + + projects.with_route.find_each(batch_size: BATCH_SIZE) do |project| + Rails.logger.info "Starting storage migration of #{project.full_path} (ID=#{project.id})..." + + begin + project.migrate_to_hashed_storage! + rescue => err + Rails.logger.error("#{err.message} migrating storage of #{project.full_path} (ID=#{project.id}), trace - #{err.backtrace}") + end + end + end + + def build_relation(start, finish) + relation = Project + table = Project.arel_table + + relation = relation.where(table[:id].gteq(start)) if start + relation = relation.where(table[:id].lteq(finish)) if finish + + relation + end +end |