Browse Source

Merge pull request #6496 from nocodb/nc-feat/table-ui

feat(nc-gui): revamped project members ui
pull/6570/head
Sreehari jayaraj 11 months ago committed by GitHub
parent
commit
2fd8311fee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      packages/nc-gui/assets/nc-icons/commentor.svg
  2. 8
      packages/nc-gui/assets/nc-icons/creator.svg
  3. 9
      packages/nc-gui/assets/nc-icons/editor.svg
  4. 8
      packages/nc-gui/assets/nc-icons/no-access.svg
  5. 8
      packages/nc-gui/assets/nc-icons/owner.svg
  6. 9
      packages/nc-gui/assets/nc-icons/viewer.svg
  7. 2
      packages/nc-gui/components/account/Profile.vue
  8. 11
      packages/nc-gui/components/account/Token.vue
  9. 2
      packages/nc-gui/components/account/UserList.vue
  10. 2
      packages/nc-gui/components/cell/TextArea.vue
  11. 2
      packages/nc-gui/components/dashboard/Sidebar/UserInfo.vue
  12. 18
      packages/nc-gui/components/general/UserIcon.vue
  13. 136
      packages/nc-gui/components/project/AccessSettings.vue
  14. 13
      packages/nc-gui/components/roles/Badge.vue
  15. 3
      packages/nc-gui/components/smartsheet/Gallery.vue
  16. 6
      packages/nc-gui/components/smartsheet/column/EditOrAdd.vue
  17. 9
      packages/nc-gui/components/smartsheet/expanded-form/Comments.vue
  18. 1
      packages/nc-gui/components/smartsheet/expanded-form/index.vue
  19. 130
      packages/nc-gui/components/workspace/CollaboratorsList.vue
  20. 130
      packages/nc-gui/utils/colorsUtils.ts
  21. 24
      packages/nc-gui/utils/iconUtils.ts
  22. 2
      packages/nc-gui/windi.config.ts
  23. 2
      packages/nocodb/src/models/BaseUser.ts

9
packages/nc-gui/assets/nc-icons/commentor.svg

@ -0,0 +1,9 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0_22_1091" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="16" height="16">
<rect width="16" height="16" fill="#D9D9D9"/>
</mask>
<g mask="url(#mask0_22_1091)">
<path d="M8 14.2V8.99998C8 8.81109 8.06389 8.65276 8.19167 8.52498C8.31944 8.3972 8.47778 8.33331 8.66667 8.33331H13.3333C13.5222 8.33331 13.6806 8.3972 13.8083 8.52498C13.9361 8.65276 14 8.81109 14 8.99998V12.3333C14 12.5222 13.9361 12.6805 13.8083 12.8083C13.6806 12.9361 13.5222 13 13.3333 13H10L8.56667 14.4333C8.45556 14.5444 8.33333 14.5722 8.2 14.5166C8.06667 14.4611 8 14.3555 8 14.2ZM9.33333 11.6666H12.6667V9.66665H9.33333V11.6666Z" fill="currentColor" stroke="none"/>
<path d="M7.33333 7.33333C6.6 7.33333 5.97222 7.07222 5.45 6.55C4.92778 6.02778 4.66667 5.4 4.66667 4.66667C4.66667 3.93333 4.92778 3.30556 5.45 2.78333C5.97222 2.26111 6.6 2 7.33333 2C8.06667 2 8.69444 2.26111 9.21667 2.78333C9.73889 3.30556 10 3.93333 10 4.66667C10 5.4 9.73889 6.02778 9.21667 6.55C8.69444 7.07222 8.06667 7.33333 7.33333 7.33333ZM7.33333 6C7.7 6 8.01389 5.86944 8.275 5.60833C8.53611 5.34722 8.66667 5.03333 8.66667 4.66667C8.66667 4.3 8.53611 3.98611 8.275 3.725C8.01389 3.46389 7.7 3.33333 7.33333 3.33333C6.96667 3.33333 6.65278 3.46389 6.39167 3.725C6.13056 3.98611 6 4.3 6 4.66667C6 5.03333 6.13056 5.34722 6.39167 5.60833C6.65278 5.86944 6.96667 6 7.33333 6ZM2 11.3333V10.8167C2 10.4389 2.09444 10.0889 2.28333 9.76667C2.47222 9.44445 2.73333 9.2 3.06667 9.03333C3.63333 8.74444 4.27222 8.5 4.98333 8.3C5.69444 8.1 6.13333 8 7 8C7 8.33331 7 8.83331 7 9.33331C6.33333 9.38887 5.52222 9.51944 5 9.69167C4.47778 9.86389 4.03889 10.0444 3.68333 10.2333C3.57222 10.2889 3.48611 10.3694 3.425 10.475C3.36389 10.5806 3.33333 10.6944 3.33333 10.8167V11.3333H6.78333V12.6132L3.33333 12.6667C2.96667 12.6667 2.65278 12.5361 2.39167 12.275C2.13056 12.0139 2 11.7 2 11.3333Z" fill="currentColor" stroke="none"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

8
packages/nc-gui/assets/nc-icons/creator.svg

@ -0,0 +1,8 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0_18_1026" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="16" height="16">
<rect width="16" height="16" fill="#D9D9D9"/>
</mask>
<g mask="url(#mask0_18_1026)">
<path d="M6.66665 8.00002C5.93331 8.00002 5.30554 7.73891 4.78331 7.21669C4.26109 6.69446 3.99998 6.06669 3.99998 5.33335C3.99998 4.60002 4.26109 3.97224 4.78331 3.45002C5.30554 2.9278 5.93331 2.66669 6.66665 2.66669C7.39998 2.66669 8.02776 2.9278 8.54998 3.45002C9.0722 3.97224 9.33331 4.60002 9.33331 5.33335C9.33331 6.06669 9.0722 6.69446 8.54998 7.21669C8.02776 7.73891 7.39998 8.00002 6.66665 8.00002ZM1.33331 12V11.4667C1.33331 11.1 1.42776 10.7556 1.61665 10.4334C1.80554 10.1111 2.06665 9.86669 2.39998 9.70002C2.96665 9.41113 3.60554 9.16669 4.31665 8.96669C5.02776 8.76669 5.81109 8.66669 6.66665 8.66669H6.89998C6.96665 8.66669 7.03331 8.6778 7.09998 8.70002C7.01109 8.90002 6.93609 9.10835 6.87498 9.32502C6.81387 9.54169 6.76665 9.76669 6.73331 10H6.66665C5.87776 10 5.16942 10.1 4.54165 10.3C3.91387 10.5 3.39998 10.7 2.99998 10.9C2.89998 10.9556 2.81942 11.0334 2.75831 11.1334C2.6972 11.2334 2.66665 11.3445 2.66665 11.4667V12H6.86665C6.93331 12.2334 7.0222 12.4639 7.13331 12.6917C7.24442 12.9195 7.36665 13.1334 7.49998 13.3334H2.66665C2.29998 13.3334 1.98609 13.2028 1.72498 12.9417C1.46387 12.6806 1.33331 12.3667 1.33331 12ZM10.5666 13.4667L10.4666 13C10.3333 12.9445 10.2083 12.8861 10.0916 12.825C9.97498 12.7639 9.85554 12.6889 9.73331 12.6L9.24998 12.75C9.10554 12.7945 8.96387 12.7889 8.82498 12.7334C8.68609 12.6778 8.57776 12.5889 8.49998 12.4667L8.36665 12.2334C8.28887 12.1 8.26109 11.9556 8.28331 11.8C8.30554 11.6445 8.37776 11.5167 8.49998 11.4167L8.86665 11.1C8.84442 10.9445 8.83331 10.8 8.83331 10.6667C8.83331 10.5334 8.84442 10.3889 8.86665 10.2334L8.49998 9.91669C8.37776 9.81669 8.30554 9.69169 8.28331 9.54169C8.26109 9.39169 8.28887 9.25002 8.36665 9.11669L8.51665 8.86669C8.59442 8.74446 8.69998 8.65558 8.83331 8.60002C8.96665 8.54446 9.10554 8.53891 9.24998 8.58335L9.73331 8.73335C9.85554 8.64446 9.97498 8.56946 10.0916 8.50835C10.2083 8.44724 10.3333 8.38891 10.4666 8.33335L10.5666 7.85002C10.6 7.69446 10.675 7.56946 10.7916 7.47502C10.9083 7.38058 11.0444 7.33335 11.2 7.33335H11.4666C11.6222 7.33335 11.7583 7.38335 11.875 7.48335C11.9916 7.58335 12.0666 7.71113 12.1 7.86669L12.2 8.33335C12.3333 8.38891 12.4583 8.45002 12.575 8.51669C12.6916 8.58335 12.8111 8.66669 12.9333 8.76669L13.3833 8.61669C13.5389 8.56113 13.6889 8.56113 13.8333 8.61669C13.9778 8.67224 14.0889 8.76669 14.1666 8.90002L14.3 9.13335C14.3778 9.26669 14.4055 9.41113 14.3833 9.56669C14.3611 9.72224 14.2889 9.85002 14.1666 9.95002L13.8 10.2667C13.8222 10.4 13.8333 10.5389 13.8333 10.6834C13.8333 10.8278 13.8222 10.9667 13.8 11.1L14.1666 11.4167C14.2889 11.5167 14.3611 11.6417 14.3833 11.7917C14.4055 11.9417 14.3778 12.0834 14.3 12.2167L14.15 12.4667C14.0722 12.5889 13.9666 12.6778 13.8333 12.7334C13.7 12.7889 13.5611 12.7945 13.4166 12.75L12.9333 12.6C12.8111 12.6889 12.6916 12.7639 12.575 12.825C12.4583 12.8861 12.3333 12.9445 12.2 13L12.1 13.4834C12.0666 13.6389 11.9916 13.7639 11.875 13.8584C11.7583 13.9528 11.6222 14 11.4666 14H11.2C11.0444 14 10.9083 13.95 10.7916 13.85C10.675 13.75 10.6 13.6222 10.5666 13.4667ZM11.3333 12C11.7 12 12.0139 11.8695 12.275 11.6084C12.5361 11.3472 12.6666 11.0334 12.6666 10.6667C12.6666 10.3 12.5361 9.98613 12.275 9.72502C12.0139 9.46391 11.7 9.33335 11.3333 9.33335C10.9666 9.33335 10.6528 9.46391 10.3916 9.72502C10.1305 9.98613 9.99998 10.3 9.99998 10.6667C9.99998 11.0334 10.1305 11.3472 10.3916 11.6084C10.6528 11.8695 10.9666 12 11.3333 12ZM6.66665 6.66669C7.03331 6.66669 7.3472 6.53613 7.60831 6.27502C7.86942 6.01391 7.99998 5.70002 7.99998 5.33335C7.99998 4.96669 7.86942 4.6528 7.60831 4.39169C7.3472 4.13058 7.03331 4.00002 6.66665 4.00002C6.29998 4.00002 5.98609 4.13058 5.72498 4.39169C5.46387 4.6528 5.33331 4.96669 5.33331 5.33335C5.33331 5.70002 5.46387 6.01391 5.72498 6.27502C5.98609 6.53613 6.29998 6.66669 6.66665 6.66669Z" fill="currentColor" stroke="none"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

9
packages/nc-gui/assets/nc-icons/editor.svg

@ -0,0 +1,9 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0_21_1063" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="16" height="16">
<rect width="16" height="16" fill="#D9D9D9"/>
</mask>
<g mask="url(#mask0_21_1063)">
<path d="M7.33333 8.00002C6.6 8.00002 5.97222 7.73891 5.45 7.21669C4.92778 6.69447 4.66667 6.06669 4.66667 5.33335C4.66667 4.60002 4.92778 3.97224 5.45 3.45002C5.97222 2.9278 6.6 2.66669 7.33333 2.66669C8.06667 2.66669 8.69444 2.9278 9.21667 3.45002C9.73889 3.97224 10 4.60002 10 5.33335C10 6.06669 9.73889 6.69447 9.21667 7.21669C8.69444 7.73891 8.06667 8.00002 7.33333 8.00002ZM2 11.4667C2 11.0889 2.09444 10.7417 2.28333 10.425C2.47222 10.1084 2.73333 9.86669 3.06667 9.70002C3.73333 9.36669 4.425 9.11113 5.14167 8.93335C5.85833 8.75558 6.58889 8.66669 7.33333 8.66669C7.72222 8.66669 8.11111 8.70002 8.5 8.76669C8.88889 8.83335 9.27778 8.91113 9.66667 9.00002L8.53333 10.1334C8.33333 10.0778 8.13333 10.0417 7.93333 10.025C7.73333 10.0084 7.53333 10 7.33333 10C6.68889 10 6.05833 10.0778 5.44167 10.2334C4.825 10.3889 4.23333 10.6111 3.66667 10.9C3.55556 10.9556 3.47222 11.0334 3.41667 11.1334C3.36111 11.2334 3.33333 11.3445 3.33333 11.4667V12H7.33333V12.65C7.33333 12.65 7.33333 13 7.33333 13.3334H3.33333C2.96667 13.3334 2.65278 13.2028 2.39167 12.9417C2.13056 12.6806 2 12.3667 2 12V11.4667ZM7.33333 6.66669C7.7 6.66669 8.01389 6.53613 8.275 6.27502C8.53611 6.01391 8.66667 5.70002 8.66667 5.33335C8.66667 4.96669 8.53611 4.6528 8.275 4.39169C8.01389 4.13058 7.7 4.00002 7.33333 4.00002C6.96667 4.00002 6.65278 4.13058 6.39167 4.39169C6.13056 4.6528 6 4.96669 6 5.33335C6 5.70002 6.13056 6.01391 6.39167 6.27502C6.65278 6.53613 6.96667 6.66669 7.33333 6.66669Z" fill="currentColor" stroke="none"/>
<path d="M7.93333 13.27V12.17C7.93333 12.0811 7.95 11.995 7.98333 11.9117C8.01667 11.8283 8.06667 11.7533 8.13333 11.6867L11.6167 8.22001C11.7167 8.12001 11.8278 8.04779 11.95 8.00334C12.0722 7.9589 12.1944 7.93668 12.3167 7.93668C12.45 7.93668 12.5778 7.96168 12.7 8.01168C12.8222 8.06168 12.9333 8.13668 13.0333 8.23668L13.65 8.85334C13.7389 8.95334 13.8083 9.06445 13.8583 9.18668C13.9083 9.3089 13.9333 9.43112 13.9333 9.55334C13.9333 9.67557 13.9111 9.80057 13.8667 9.92834C13.8222 10.0561 13.75 10.17 13.65 10.27L10.1833 13.7367C10.1167 13.8033 10.0417 13.8533 9.95833 13.8867C9.875 13.92 9.78889 13.9367 9.7 13.9367H8.6C8.41111 13.9367 8.25278 13.8728 8.125 13.745C7.99722 13.6172 7.93333 13.4589 7.93333 13.27ZM8.93333 12.9367H9.56667L11.5833 10.9033L11.2833 10.5867L10.9667 10.2867L8.93333 12.3033V12.9367ZM11.2833 10.5867L10.9667 10.2867L11.5833 10.9033L11.2833 10.5867Z" fill="currentColor" stroke="none"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

8
packages/nc-gui/assets/nc-icons/no-access.svg

@ -0,0 +1,8 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0_18_1051" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="16" height="16">
<rect width="16" height="16" fill="#D9D9D9"/>
</mask>
<g mask="url(#mask0_18_1051)">
<path d="M10.1333 7.29998L7.03331 4.19998C7.18887 4.13331 7.3472 4.08331 7.50831 4.04998C7.66942 4.01665 7.83331 3.99998 7.99998 3.99998C8.65553 3.99998 9.20831 4.22498 9.65831 4.67498C10.1083 5.12498 10.3333 5.67776 10.3333 6.33331C10.3333 6.49998 10.3166 6.66387 10.2833 6.82498C10.25 6.98609 10.2 7.14442 10.1333 7.29998ZM3.89998 11.4C4.46665 10.9666 5.09998 10.625 5.79998 10.375C6.49998 10.125 7.23331 9.99998 7.99998 9.99998C8.19998 9.99998 8.39165 10.0083 8.57498 10.025C8.75831 10.0416 8.94998 10.0666 9.14998 10.1L7.68331 8.63331C7.16109 8.56665 6.71387 8.3472 6.34165 7.97498C5.96942 7.60276 5.74998 7.15554 5.68331 6.63331L3.78331 4.73331C3.42776 5.18887 3.15276 5.69165 2.95831 6.24165C2.76387 6.79165 2.66665 7.37776 2.66665 7.99998C2.66665 8.65553 2.77498 9.2722 2.99165 9.84998C3.20831 10.4278 3.51109 10.9444 3.89998 11.4ZM12.2 11.2666C12.5555 10.8111 12.8333 10.3083 13.0333 9.75831C13.2333 9.20831 13.3333 8.6222 13.3333 7.99998C13.3333 6.5222 12.8139 5.26387 11.775 4.22498C10.7361 3.18609 9.47776 2.66665 7.99998 2.66665C7.37776 2.66665 6.79165 2.76665 6.24165 2.96665C5.69165 3.16665 5.18887 3.44442 4.73331 3.79998L12.2 11.2666ZM7.99998 14.6666C7.08887 14.6666 6.22776 14.4916 5.41665 14.1416C4.60554 13.7916 3.8972 13.3139 3.29165 12.7083C2.68609 12.1028 2.20831 11.3944 1.85831 10.5833C1.50831 9.7722 1.33331 8.91109 1.33331 7.99998C1.33331 7.07776 1.50831 6.21387 1.85831 5.40831C2.20831 4.60276 2.68609 3.8972 3.29165 3.29165C3.8972 2.68609 4.60554 2.20831 5.41665 1.85831C6.22776 1.50831 7.08887 1.33331 7.99998 1.33331C8.9222 1.33331 9.78609 1.50831 10.5916 1.85831C11.3972 2.20831 12.1028 2.68609 12.7083 3.29165C13.3139 3.8972 13.7916 4.60276 14.1416 5.40831C14.4916 6.21387 14.6666 7.07776 14.6666 7.99998C14.6666 8.91109 14.4916 9.7722 14.1416 10.5833C13.7916 11.3944 13.3139 12.1028 12.7083 12.7083C12.1028 13.3139 11.3972 13.7916 10.5916 14.1416C9.78609 14.4916 8.9222 14.6666 7.99998 14.6666ZM7.99998 13.3333C8.58887 13.3333 9.14442 13.2472 9.66665 13.075C10.1889 12.9028 10.6666 12.6555 11.1 12.3333C10.6666 12.0111 10.1889 11.7639 9.66665 11.5916C9.14442 11.4194 8.58887 11.3333 7.99998 11.3333C7.41109 11.3333 6.85554 11.4194 6.33331 11.5916C5.81109 11.7639 5.33331 12.0111 4.89998 12.3333C5.33331 12.6555 5.81109 12.9028 6.33331 13.075C6.85554 13.2472 7.41109 13.3333 7.99998 13.3333Z" fill="currentColor" stroke="none"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

8
packages/nc-gui/assets/nc-icons/owner.svg

@ -0,0 +1,8 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0_18_1022" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="16" height="16">
<rect width="16" height="16" fill="currentColor"/>
</mask>
<g mask="url(#mask0_18_1022)">
<path d="M7.99999 9.20002C7.33332 9.20002 6.76665 8.96668 6.29999 8.50002C5.83332 8.03335 5.59999 7.46668 5.59999 6.80002C5.59999 6.13335 5.83332 5.56668 6.29999 5.10002C6.76665 4.63335 7.33332 4.40002 7.99999 4.40002C8.66665 4.40002 9.23332 4.63335 9.69999 5.10002C10.1667 5.56668 10.4 6.13335 10.4 6.80002C10.4 7.46668 10.1667 8.03335 9.69999 8.50002C9.23332 8.96668 8.66665 9.20002 7.99999 9.20002ZM7.99999 8.00002C8.33332 8.00002 8.61665 7.88335 8.84999 7.65002C9.08332 7.41668 9.19999 7.13335 9.19999 6.80002C9.19999 6.46668 9.08332 6.18335 8.84999 5.95002C8.61665 5.71668 8.33332 5.60002 7.99999 5.60002C7.66665 5.60002 7.38332 5.71668 7.14999 5.95002C6.91665 6.18335 6.79999 6.46668 6.79999 6.80002C6.79999 7.13335 6.91665 7.41668 7.14999 7.65002C7.38332 7.88335 7.66665 8.00002 7.99999 8.00002ZM7.99999 2.88335L3.99999 4.41668V7.41668C3.99999 8.00557 4.08332 8.57779 4.24999 9.13335C4.41665 9.6889 4.64443 10.2056 4.93332 10.6833C5.4111 10.4611 5.90832 10.2917 6.42499 10.175C6.94165 10.0583 7.46665 10 7.99999 10C8.53332 10 9.05832 10.0583 9.57499 10.175C10.0917 10.2917 10.5889 10.4611 11.0667 10.6833C11.3555 10.2056 11.5833 9.6889 11.75 9.13335C11.9167 8.57779 12 8.00557 12 7.41668V4.41668L7.99999 2.88335ZM7.99999 11.2C7.59999 11.2 7.20554 11.2389 6.81665 11.3167C6.42777 11.3945 6.04999 11.5111 5.68332 11.6667C6.00554 12.0111 6.3611 12.3111 6.74999 12.5667C7.13888 12.8222 7.55554 13.0167 7.99999 13.15C8.44443 13.0167 8.8611 12.8222 9.24999 12.5667C9.63888 12.3111 9.99443 12.0111 10.3167 11.6667C9.94999 11.5111 9.57221 11.3945 9.18332 11.3167C8.79443 11.2389 8.39999 11.2 7.99999 11.2ZM7.99999 14.3333C7.93332 14.3333 7.86665 14.3306 7.79999 14.325C7.73332 14.3195 7.67221 14.3056 7.61665 14.2833C6.1611 13.8056 4.99443 12.9222 4.11665 11.6333C3.23888 10.3445 2.79999 8.93891 2.79999 7.41668V4.41668C2.79999 4.16113 2.86943 3.93335 3.00832 3.73335C3.14721 3.53335 3.33332 3.38891 3.56665 3.30002L7.56665 1.76668C7.7111 1.71113 7.85554 1.68335 7.99999 1.68335C8.14443 1.68335 8.28888 1.71113 8.43332 1.76668L12.4333 3.30002C12.6667 3.38891 12.8528 3.53335 12.9917 3.73335C13.1305 3.93335 13.2 4.16113 13.2 4.41668V7.41668C13.2 8.93891 12.7611 10.3445 11.8833 11.6333C11.0055 12.9222 9.83888 13.8056 8.38332 14.2833C8.32777 14.3056 8.26665 14.3195 8.19999 14.325C8.13332 14.3306 8.06665 14.3333 7.99999 14.3333Z" fill="currentColor" stroke="none"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

9
packages/nc-gui/assets/nc-icons/viewer.svg

@ -0,0 +1,9 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0_18_1042" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="16" height="16">
<rect width="16" height="16" fill="#D9D9D9"/>
</mask>
<g mask="url(#mask0_18_1042)">
<path d="M6.66665 8.00002C5.93331 8.00002 5.30554 7.73891 4.78331 7.21669C4.26109 6.69447 3.99998 6.06669 3.99998 5.33335C3.99998 4.60002 4.26109 3.97224 4.78331 3.45002C5.30554 2.9278 5.93331 2.66669 6.66665 2.66669C7.39998 2.66669 8.02776 2.9278 8.54998 3.45002C9.0722 3.97224 9.33331 4.60002 9.33331 5.33335C9.33331 6.06669 9.0722 6.69447 8.54998 7.21669C8.02776 7.73891 7.39998 8.00002 6.66665 8.00002ZM1.33331 12V11.4667C1.33331 11.1 1.42776 10.7556 1.61665 10.4334C1.80554 10.1111 2.06665 9.86669 2.39998 9.70002C2.96665 9.41113 3.60554 9.16669 4.31665 8.96669C4.71274 8.85529 4.93609 8.67502 5.79165 8.67502H6.02498C6.09165 8.67502 6.15831 8.68613 6.22498 8.70835C5.99998 9.00002 5.33331 9.66669 4.99998 10C4.99998 10 4.8376 10.2057 4.54165 10.3C3.91387 10.5 3.39998 10.7 2.99998 10.9C2.89998 10.9556 2.81942 11.0334 2.75831 11.1334C2.6972 11.2334 2.66665 11.3445 2.66665 11.4667V12H4.99998C5.33331 12.3334 5.33331 12.3334 5.66665 12.6917C5.90596 12.949 6.19998 13.1334 6.33331 13.3334H2.66665C2.29998 13.3334 1.98609 13.2028 1.72498 12.9417C1.46387 12.6806 1.33331 12.3667 1.33331 12ZM6.66665 6.66669C7.03331 6.66669 7.3472 6.53613 7.60831 6.27502C7.86942 6.01391 7.99998 5.70002 7.99998 5.33335C7.99998 4.96669 7.86942 4.6528 7.60831 4.39169C7.3472 4.13058 7.03331 4.00002 6.66665 4.00002C6.29998 4.00002 5.98609 4.13058 5.72498 4.39169C5.46387 4.6528 5.33331 4.96669 5.33331 5.33335C5.33331 5.70002 5.46387 6.01391 5.72498 6.27502C5.98609 6.53613 6.29998 6.66669 6.66665 6.66669Z" fill="currentColor" stroke="none"/>
<path d="M9.99998 12.6667C10.6555 12.6667 11.2639 12.5167 11.825 12.2167C12.3861 11.9167 12.8333 11.5111 13.1666 11C12.8333 10.4889 12.3861 10.0833 11.825 9.78333C11.2639 9.48333 10.6555 9.33333 9.99998 9.33333C9.34442 9.33333 8.73609 9.48333 8.17498 9.78333C7.61387 10.0833 7.16665 10.4889 6.83331 11C7.16665 11.5111 7.61387 11.9167 8.17498 12.2167C8.73609 12.5167 9.34442 12.6667 9.99998 12.6667ZM9.99998 14C8.93331 14 7.98054 13.7194 7.14165 13.1583C6.30276 12.5972 5.69998 11.8778 5.33331 11C5.69998 10.1222 6.30276 9.40278 7.14165 8.84167C7.98054 8.28056 8.93331 8 9.99998 8C11.0666 8 12.0194 8.28056 12.8583 8.84167C13.6972 9.40278 14.3 10.1222 14.6666 11C14.3 11.8778 13.6972 12.5972 12.8583 13.1583C12.0194 13.7194 11.0666 14 9.99998 14ZM9.99998 12C9.7222 12 9.48609 11.9028 9.29165 11.7083C9.0972 11.5139 8.99998 11.2778 8.99998 11C8.99998 10.7222 9.0972 10.4861 9.29165 10.2917C9.48609 10.0972 9.7222 10 9.99998 10C10.2778 10 10.5139 10.0972 10.7083 10.2917C10.9028 10.4861 11 10.7222 11 11C11 11.2778 10.9028 11.5139 10.7083 11.7083C10.5139 11.9028 10.2778 12 9.99998 12Z" fill="currentColor" stroke="none"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

2
packages/nc-gui/components/account/Profile.vue

@ -69,7 +69,7 @@ const onValidate = async (_: any, valid: boolean) => {
<div class="flex text-gray-500">{{ $t('labels.controlAppearance') }}</div>
<div class="flex flex-row mt-4">
<div class="flex h-20 mt-1.5">
<GeneralUserIcon size="xlarge" />
<GeneralUserIcon size="xlarge" :email="user?.email" />
</div>
<div class="flex w-10"></div>
<a-form

11
packages/nc-gui/components/account/Token.vue

@ -181,9 +181,9 @@ const handleCancel = () => {
</NcButton>
</div>
<span>{{ $t('msg.apiTokenCreate') }}</span>
<div class="w-[780px] mt-5 border-1 rounded-md h-[530px] overflow-y-scroll">
<div class="w-full mt-5 rounded-md h-136 overflow-y-scroll">
<div>
<div class="flex w-full pl-5 bg-gray-50 border-b-1">
<div class="flex w-full pl-5 bg-gray-50 border-1">
<span class="py-3.5 text-gray-500 font-medium text-3.5 w-2/9">{{ $t('title.tokenName') }}</span>
<span class="py-3.5 text-gray-500 font-medium text-3.5 w-2/9 text-start">{{ $t('title.creator') }}</span>
<span class="py-3.5 text-gray-500 font-medium text-3.5 w-3/9 text-start">{{ $t('labels.token') }}</span>
@ -226,7 +226,12 @@ const handleCancel = () => {
<a-empty :image="Empty.PRESENTED_IMAGE_SIMPLE" :description="$t('title.noLabels')" />
</div>
<div v-for="el of tokens" :key="el.id" data-testid="nc-token-list" class="flex border-b-1 pl-5 py-3 justify-between">
<div
v-for="el of tokens"
:key="el.id"
data-testid="nc-token-list"
class="flex border-1 pl-5 py-3 justify-between token"
>
<span class="text-black font-bold text-3.5 text-start w-2/9">
<GeneralTruncateText placement="top" length="20">
{{ el.description }}

2
packages/nc-gui/components/account/UserList.vue

@ -172,7 +172,7 @@ const openDeleteModal = (user: UserType) => {
</NcButton>
</div>
</div>
<div class="w-[780px] mt-5 border-1 rounded-md h-[613px]">
<div class="w-full mt-5 border-1 rounded-md h-[613px] max-w-250">
<div class="flex w-full bg-gray-50 border-b-1">
<span class="py-3.5 text-gray-500 font-medium text-3.5 w-1/3 text-start pl-10">{{ $t('labels.email') }}</span>
<span class="py-3.5 text-gray-500 font-medium text-3.5 w-1/3 text-start pl-20">{{ $t('objects.role') }}</span>

2
packages/nc-gui/components/cell/TextArea.vue

@ -113,7 +113,7 @@ onClickOutside(inputWrapperRef, (e) => {
<span v-else>{{ vModel }}</span>
<div
v-if="active"
v-if="active && !isExpandedFormOpen"
class="!absolute right-0 bottom-0 h-6 w-5 group cursor-pointer flex justify-end gap-1 items-center active:(ring ring-accent ring-opacity-100) rounded border-none p-1 hover:(bg-primary bg-opacity-10) dark:(!bg-slate-500)"
:class="{ 'right-2 bottom-2': editEnabled }"
data-testid="attachment-cell-file-picker-button"

2
packages/nc-gui/components/dashboard/Sidebar/UserInfo.vue

@ -85,7 +85,7 @@ onMounted(() => {
class="flex flex-row py-2 px-3 gap-x-2 items-center hover:bg-gray-200 rounded-lg cursor-pointer h-10"
data-testid="nc-sidebar-userinfo"
>
<GeneralUserIcon />
<GeneralUserIcon :email="user?.email" size="base" />
<div class="flex truncate">
{{ name ? name : user?.email }}
</div>

18
packages/nc-gui/components/general/UserIcon.vue

@ -1,4 +1,6 @@
<script lang="ts" setup>
import { isColorDark, stringToColor } from '~/utils/colorsUtils'
const props = withDefaults(
defineProps<{
size?: 'small' | 'medium' | 'base' | 'large' | 'xlarge'
@ -10,24 +12,22 @@ const props = withDefaults(
},
)
const { user } = useGlobal()
const emailProp = toRef(props, 'email')
const backgroundColor = computed(() => {
// in comments we need to generate user icon from email
if (emailProp.value.length) {
return stringToColour(emailProp.value)
return stringToColor(emailProp.value)
}
return user.value?.email ? stringToColour(user.value?.email) : '#FFFFFF'
return props.email ? stringToColor(props.email) : '#FFFFFF'
})
const size = computed(() => props.size || 'medium')
const displayName = computed(() => props.name ?? user.value?.display_name ?? '')
const displayName = computed(() => props.email ?? '')
const email = computed(() => props.name ?? user.value?.email ?? '')
const email = computed(() => props.name ?? props?.email ?? '')
const usernameInitials = computed(() => {
const displayNameSplit = displayName.value?.split(' ').filter((name) => name) ?? []
@ -46,13 +46,15 @@ const usernameInitials = computed(() => {
<template>
<div
class="flex nc-user-avatar"
class="flex nc-user-avatar font-bold"
:class="{
'min-w-4 min-h-4': size === 'small',
'min-w-6 min-h-6': size === 'medium',
'w-8 h-8 !text-md': size === 'base',
'min-w-20 min-h-20 !text-3xl': size === 'large',
'min-w-26 min-h-26 !text-4xl': size === 'xlarge',
'text-white': isColorDark(backgroundColor),
'text-black': !isColorDark(backgroundColor),
}"
:style="{ backgroundColor }"
>
@ -62,6 +64,6 @@ const usernameInitials = computed(() => {
<style lang="scss" scoped>
.nc-user-avatar {
@apply rounded-full text-xs flex items-center justify-center text-white uppercase;
@apply rounded-full text-xs flex items-center justify-center uppercase;
}
</style>

136
packages/nc-gui/components/project/AccessSettings.vue

@ -2,7 +2,7 @@
import type { OrgUserRoles, WorkspaceUserRoles } from 'nocodb-sdk'
import { OrderedProjectRoles, ProjectRoles, WorkspaceRolesToProjectRoles } from 'nocodb-sdk'
import InfiniteLoading from 'v3-infinite-loading'
import { isEeUI, storeToRefs, stringToColour, timeAgo } from '#imports'
import { isEeUI, storeToRefs, timeAgo } from '#imports'
const basesStore = useBases()
const { getProjectUsers, createProjectUser, updateProjectUser, removeProjectUser } = basesStore
@ -10,16 +10,15 @@ const { activeProjectId } = storeToRefs(basesStore)
const { baseRoles } = useRoles()
const collaborators = ref<
{
id: string
email: string
main_roles: OrgUserRoles
roles: ProjectRoles
workspace_roles: WorkspaceUserRoles
created_at: string
}[]
>([])
interface Collaborators {
id: string
email: string
main_roles: OrgUserRoles
roles: ProjectRoles
workspace_roles: WorkspaceUserRoles
created_at: string
}
const collaborators = ref<Collaborators[]>([])
const totalCollaborators = ref(0)
const userSearchText = ref('')
const currentPage = ref(0)
@ -75,12 +74,6 @@ const loadListData = async ($state: any) => {
$state.loaded()
}
const reloadCollabs = async () => {
currentPage.value = 0
collaborators.value = []
await loadCollaborators()
}
const updateCollaborator = async (collab: any, roles: ProjectRoles) => {
try {
if (
@ -107,8 +100,7 @@ const updateCollaborator = async (collab: any, roles: ProjectRoles) => {
}
} catch (e: any) {
message.error(await extractSdkResponseErrorMsg(e))
} finally {
reloadCollabs()
loadCollaborators()
}
}
@ -154,12 +146,12 @@ onMounted(async () => {
</script>
<template>
<div class="nc-collaborator-table-container mt-4 nc-access-settings-view">
<div class="nc-collaborator-table-container mt-4 nc-access-settings-view h-[calc(100vh-8rem)]">
<div v-if="isLoading" class="nc-collaborators-list items-center justify-center">
<GeneralLoader size="xlarge" />
</div>
<template v-else>
<div class="w-full flex flex-row justify-between items-baseline mt-6.5 mb-2 pr-0.25 ml-2">
<div class="w-full flex flex-row justify-between items-baseline mt-6.5 mb-2 pr-0.25">
<a-input v-model:value="userSearchText" class="!max-w-90 !rounded-md" :placeholder="$t('title.searchMembers')">
<template #prefix>
<PhMagnifyingGlassBold class="!h-3.5 text-gray-500" />
@ -170,40 +162,35 @@ onMounted(async () => {
<div v-if="isSearching" class="nc-collaborators-list items-center justify-center">
<GeneralLoader size="xlarge" />
</div>
<div
v-else-if="!collaborators?.length"
class="nc-collaborators-list w-full h-full flex flex-col items-center justify-center mt-36"
>
<!-- <Empty :description="$t('title.noMembersFound')" /> -->
<Empty description="$t('title.noMembersFound')" />
</div>
<div v-else class="nc-collaborators-list nc-scrollbar-md">
<div class="nc-collaborators-list-header">
<div class="flex w-3/5">{{ $t('objects.users') }}</div>
<div class="flex w-2/5">{{ $t('title.dateJoined') }}</div>
<div class="flex w-1/5">{{ $t('general.access') }}</div>
<div class="flex w-1/5"></div>
<div class="flex w-1/5"></div>
</div>
<div v-else class="nc-collaborators-list mt-6 h-full">
<div class="flex flex-col rounded-lg overflow-hidden border-1 max-w-350 max-h-[calc(100%-8rem)]">
<div class="flex flex-row bg-gray-50 min-h-12 items-center">
<div class="text-gray-700 users-email-grid">{{ $t('objects.users') }}</div>
<div class="text-gray-700 date-joined-grid">{{ $t('title.dateJoined') }}</div>
<div class="text-gray-700 user-access-grid">{{ $t('general.access') }}</div>
</div>
<div class="flex flex-col nc-scrollbar-md">
<div v-for="(collab, i) of collaborators" :key="i" class="relative w-full nc-collaborators nc-collaborators-list-row">
<div class="!py-0 w-3/5 email truncate">
<div class="flex items-center gap-2">
<span class="color-band" :style="{ backgroundColor: stringToColour(collab.email) }">{{
collab?.email?.slice(0, 2)
}}</span>
<!-- <GeneralTruncateText> -->
<div class="flex flex-col nc-scrollbar-md">
<div
v-for="(collab, i) of collaborators"
:key="i"
class="user-row flex flex-row border-b-1 py-1 min-h-14 items-center"
>
<div class="flex gap-3 items-center users-email-grid">
<GeneralUserIcon size="base" :name="collab.email" :email="collab.email" />
<span class="truncate">
{{ collab.email }}
</span>
<!-- </GeneralTruncateText> -->
</div>
</div>
<div class="text-gray-500 text-xs w-2/5 created-at truncate">
{{ timeAgo(collab.created_at) }}
</div>
<div class="w-1/5 roles">
<div class="nc-collaborator-role-select p-2">
<div class="date-joined-grid">{{ timeAgo(collab.created_at) }}</div>
<div class="user-access-grid">
<template v-if="accessibleRoles.includes(collab.roles)">
<RolesSelector
:role="collab.roles"
@ -218,57 +205,58 @@ onMounted(async () => {
/>
</template>
<template v-else>
<RolesBadge class="!bg-white" :role="collab.roles" />
<RolesBadge :role="collab.roles" />
</template>
</div>
</div>
<div class="w-1/5"></div>
<div class="w-1/5"></div>
</div>
<InfiniteLoading v-bind="$attrs" @infinite="loadListData">
<template #spinner>
<div class="flex flex-row w-full justify-center mt-2">
<GeneralLoader />
</div>
</template>
<template #complete>
<span></span>
</template>
</InfiniteLoading>
</div>
<InfiniteLoading v-bind="$attrs" @infinite="loadListData">
<template #spinner>
<div class="flex flex-row w-full justify-center mt-2">
<GeneralLoader />
</div>
</template>
<template #complete>
<span></span>
</template>
</InfiniteLoading>
</div>
</template>
</div>
</template>
<style scoped lang="scss">
.badge-text {
@apply text-[14px] flex items-center justify-center gap-1 pt-0.5;
.color-band {
@apply w-6 h-6 left-0 top-2.5 rounded-full flex justify-center uppercase text-white font-weight-bold text-xs items-center;
}
.nc-collaborators-list {
@apply border-gray-100 mt-1 flex flex-col w-full;
// todo: replace/remove 120px with proper value while updating invite ui
height: calc(100vh - calc(var(--topbar-height) + 9rem + 120px));
:deep(.nc-collaborator-role-select .ant-select-selector) {
@apply !rounded;
}
.nc-collaborators-list-header {
@apply flex flex-row justify-between items-center min-h-13 border-b-1 border-gray-100 pl-4 text-gray-500;
:deep(.ant-select-selection-item) {
@apply mt-0.75;
}
.nc-collaborators-list-row {
@apply flex flex-row justify-between items-center min-h-16 border-b-1 border-gray-100 pl-4;
.users-email-grid {
@apply flex-grow ml-4 w-1/2;
}
.color-band {
@apply w-6 h-6 left-0 top-[10px] rounded-full flex justify-center uppercase text-white font-weight-bold text-xs items-center;
.date-joined-grid {
@apply flex items-start;
width: calc(50% - 10rem);
}
:deep(.nc-collaborator-role-select .ant-select-selector) {
@apply !rounded;
.user-access-grid {
@apply w-40;
}
:deep(.ant-select-selection-item) {
@apply mt-0.75;
.user-row {
@apply w-full;
}
.user-row:last-child {
@apply border-b-0;
}
</style>

13
packages/nc-gui/components/roles/Badge.vue

@ -50,12 +50,12 @@ const roleProperties = computed(() => {
<div
class="badge-text flex items-center gap-2"
:class="{
'text-purple-500': roleProperties.color === 'purple',
'text-blue-500': roleProperties.color === 'blue',
'text-green-500': roleProperties.color === 'green',
'text-orange-500': roleProperties.color === 'orange',
'text-yellow-500': roleProperties.color === 'yellow',
'text-red-500': roleProperties.color === 'red',
'text-purple-700': roleProperties.color === 'purple',
'text-blue-700': roleProperties.color === 'blue',
'text-green-700': roleProperties.color === 'green',
'text-orange-700': roleProperties.color === 'orange',
'text-yellow-700': roleProperties.color === 'yellow',
'text-red-700': roleProperties.color === 'red',
'text-gray-300': !roleProperties.color,
sizeSelect,
}"
@ -67,7 +67,6 @@ const roleProperties = computed(() => {
<GeneralIcon v-if="clickableRef" icon="arrowDown" />
</div>
</NcBadge>
<div class="flex-1"></div>
<!--
<a-tooltip v-if="inheritRef" placement="bottom">
<div class="text-gray-400 text-xs p-1 rounded-md">Workspace Role</div>

3
packages/nc-gui/components/smartsheet/Gallery.vue

@ -7,7 +7,6 @@ import {
IsFormInj,
IsGalleryInj,
IsGridInj,
IsPublicInj,
MetaInj,
NavigateDir,
OpenNewRecordFormHookInj,
@ -61,8 +60,6 @@ provide(IsGridInj, ref(false))
provide(RowHeightInj, ref(1 as const))
const isPublic = inject(IsPublicInj, ref(false))
const fields = inject(FieldsInj, ref([]))
const route = useRoute()

6
packages/nc-gui/components/smartsheet/column/EditOrAdd.vue

@ -58,7 +58,7 @@ const { betaFeatureToggleState } = useBetaFeatureToggle()
const { openedViewsTab } = storeToRefs(useViewsStore())
const { loadMagic, predictColumnType: _predictColumnType } = useNocoEe()
const { predictColumnType: _predictColumnType } = useNocoEe()
const meta = inject(MetaInj, ref())
@ -145,10 +145,6 @@ watchEffect(() => {
advancedOptions.value = false
})
const predictColumnType = async () => {
_predictColumnType(formState, onUidtOrIdTypeChange)
}
onMounted(() => {
if (!isEdit.value) {
generateNewColumnMeta()

9
packages/nc-gui/components/smartsheet/expanded-form/Comments.vue

@ -8,10 +8,6 @@ const { loadCommentsAndLogs, commentsAndLogs, saveComment: _saveComment, comment
const commentsWrapperEl = ref<HTMLDivElement>()
const auditTabDomRef = (e: HTMLElement) => {
e.scrollTop = e.scrollHeight
}
onMounted(async () => {
await loadCommentsAndLogs()
})
@ -232,7 +228,7 @@ const processedAudit = (log: string) => {
</div>
</div>
</div>
<div v-if="tab === 'audits'" :ref="auditTabDomRef" class="flex flex-col h-full pl-2 pr-1 pt-2 nc-scrollbar-md space-y-2">
<div v-if="tab === 'audits'" ref="commentsWrapperEl" class="flex flex-col h-full pl-2 pr-1 pt-2 nc-scrollbar-md space-y-2">
<template v-if="audits.length === 0">
<div class="flex flex-col text-center justify-center h-full">
<div class="text-center text-3xl text-gray-600">
@ -246,8 +242,7 @@ const processedAudit = (log: string) => {
<div class="flex flex-col p-4 gap-3">
<div class="flex justify-between">
<div class="flex items-center gap-2">
<GeneralUserIcon size="base" :name="log.display_name ?? log.user" />
<GeneralUserIcon size="base" :email="log.user" />
<div class="flex flex-col">
<span class="truncate font-bold max-w-50">
{{ log.display_name ?? log.user.split('@')[0].slice(0, 2) ?? 'Shared source' }}

1
packages/nc-gui/components/smartsheet/expanded-form/index.vue

@ -3,7 +3,6 @@ import type { TableType, ViewType } from 'nocodb-sdk'
import { isLinksOrLTAR, isSystemColumn, isVirtualCol } from 'nocodb-sdk'
import type { Ref } from 'vue'
import MdiChevronDown from '~icons/mdi/chevron-down'
import TableIcon from '~icons/nc-icons/table'
import {
CellClickHookInj,

130
packages/nc-gui/components/workspace/CollaboratorsList.vue

@ -56,31 +56,33 @@ onMounted(async () => {
<div v-if="!filterCollaborators?.length" class="w-full h-full flex flex-col items-center justify-center mt-36">
<Empty description="No members found" />
</div>
<table v-else class="nc-collaborators-list-table !nc-scrollbar-md">
<thead>
<tr>
<th class="w-1/5">Users</th>
<th class="w-1/5">Date Joined</th>
<th class="w-1/5">Access</th>
<th class="w-1/5"></th>
<th class="w-1/5"></th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="(collab, i) of filterCollaborators" :key="i" class="relative w-full nc-collaborators">
<td class="!py-0 w-1/5 email">
<div v-else class="nc-collaborators-list !mt-10 nc-scrollbar-md rounded-md">
<div class="nc-collaborators-list-header bg-gray-50 rounded-t-md">
<div class="flex w-2/5 text-gray-600">Users</div>
<div class="flex w-2/5 text-gray-600">Date Joined</div>
<div class="flex w-2/5 text-gray-600">Access</div>
<div class="flex w-2/5 text-gray-600">Action</div>
</div>
<div class="flex flex-col nc-scrollbar-md">
<div
v-for="(collab, i) of filterCollaborators"
:key="i"
class="relative w-full nc-collaborators nc-collaborators-list-row"
>
<div class="!py-0 w-2/5 email truncate">
<div class="flex items-center gap-2">
<span class="color-band" :style="{ backgroundColor: stringToColour(collab.email) }">{{
collab.email.slice(0, 2)
}}</span>
{{ collab.email }}
<span class="truncate">
{{ collab.email }}
</span>
</div>
</td>
<td class="text-gray-500 text-xs w-1/5 created-at">
</div>
<div class="text-gray-500 text-xs w-2/5 created-at truncate">
{{ timeAgo(collab.created_at) }}
</td>
<td class="w-1/5 roles">
</div>
<div class="w-2/5 roles">
<div class="nc-collaborator-role-select">
<template v-if="accessibleRoles.includes(collab.roles)">
<RolesSelector
@ -94,29 +96,25 @@ onMounted(async () => {
<RolesBadge class="!bg-white" :role="collab.roles" />
</template>
</div>
</td>
<td class="w-1/5">
<div class="-left-2.5 top-5">
<NcDropdown v-if="collab.roles !== WorkspaceUserRoles.OWNER" :trigger="['click']">
<MdiDotsVertical
class="border-1 !text-gray-600 h-5.5 w-5.5 rounded outline-0 p-0.5 nc-workspace-menu transform transition-transform !text-gray-400 cursor-pointer hover:(!text-gray-500 bg-gray-100)"
/>
<template #overlay>
<NcMenu>
<NcMenuItem class="!text-red-500 !hover:bg-red-50" @click="removeCollaborator(collab.id)">
<MaterialSymbolsDeleteOutlineRounded />
Remove user
</NcMenuItem>
</NcMenu>
</template>
</NcDropdown>
</div>
</td>
<td class="w-1/5 padding"></td>
<td class="w-1/5 padding"></td>
</tr>
</tbody>
</table>
</div>
<div class="w-2/5 pl-5">
<NcDropdown v-if="collab.roles !== WorkspaceUserRoles.OWNER" :trigger="['click']">
<MdiDotsVertical
class="border-1 !text-gray-600 h-5.5 w-5.5 rounded outline-0 p-0.5 nc-workspace-menu transform transition-transform !text-gray-400 cursor-pointer hover:(!text-gray-500 bg-gray-100)"
/>
<template #overlay>
<NcMenu>
<NcMenuItem class="!text-red-500 !hover:bg-red-50" @click="removeCollaborator(collab.id)">
<MaterialSymbolsDeleteOutlineRounded />
Remove user
</NcMenuItem>
</NcMenu>
</template>
</NcDropdown>
</div>
</div>
</div>
</div>
</div>
</template>
@ -125,6 +123,32 @@ onMounted(async () => {
@apply text-[14px] pt-1 text-center;
}
.nc-collaborators-list {
@apply border-2 shadow-sm border-gray-100 mt-1 flex flex-col w-full;
// todo: replace/remove 120px with proper value while updating invite ui
height: calc(100vh - calc(var(--topbar-height) + 9rem + 120px));
}
.nc-collaborators-list-header {
@apply flex flex-row justify-between items-center min-h-10 border-b-2 shadow-sm border-gray-100 pl-4;
}
.nc-collaborators-list-row {
@apply flex flex-row justify-between items-center min-h-16 border-b-2 shadow-sm border-gray-100 pl-4;
}
.color-band {
@apply w-6 h-6 left-0 top-[10px] rounded-full flex justify-center uppercase text-white font-weight-bold text-xs items-center;
}
:deep(.nc-collaborator-role-select .ant-select-selector) {
@apply !rounded;
}
:deep(.ant-select-selection-item) {
@apply mt-0.75;
}
.nc-collaborators-list-table {
@apply min-w-[700px] !w-full border-gray-100 mt-1;
@ -154,26 +178,21 @@ onMounted(async () => {
}
}
.color-band {
@apply w-6 h-6 left-0 top-[10px] rounded-full flex justify-center uppercase text-white font-weight-bold text-xs items-center;
}
:deep(.nc-collaborator-role-select .ant-select-selector) {
@apply !rounded;
}
table {
display: block;
width: 100%;
}
thead {
display: block;
width: 100%;
}
tr {
display: block;
width: 100%;
}
tbody {
display: block;
width: 100%;
@ -183,32 +202,35 @@ tbody {
&::-webkit-scrollbar {
width: 4px;
}
&::-webkit-scrollbar-track {
background: #f6f6f600 !important;
}
&::-webkit-scrollbar-thumb {
background: #f6f6f600;
}
&::-webkit-scrollbar-thumb:hover {
background: #f6f6f600;
}
}
tbody {
&::-webkit-scrollbar {
width: 4px;
}
&::-webkit-scrollbar-track {
background: #f6f6f600 !important;
}
&::-webkit-scrollbar-thumb {
background: rgb(215, 215, 215);
}
&::-webkit-scrollbar-thumb:hover {
background: rgb(203, 203, 203);
}
}
:deep(.ant-select-selection-item) {
@apply mt-0.75;
}
</style>

130
packages/nc-gui/utils/colorsUtils.ts

@ -111,17 +111,127 @@ export const baseThemeColors = [
'#333333',
]
const designSystem = {
light: [
'#EBF0FF',
'#D6E0FF',
'#ADC2FF',
'#85A3FF',
'#5C85FF',
'#3366FF',
'#2952CC',
'#1F3D99',
'#142966',
'#0A1433',
'#FCFCFC',
'#F9F9FA',
'#F4F4F5',
'#E7E7E9',
'#D5D5D9',
'#9AA2AF',
'#6A7184',
'#4A5268',
'#374151',
'#1F293A',
'#101015',
'#FFF2F1',
'#FFDBD9',
'#FFB7B2',
'#FF928C',
'#FF6E65',
'#FF4A3F',
'#E8463C',
'#CB3F36',
'#B23830',
'#7D2721',
'#FFEEFB',
'#FED8F4',
'#FEB0E8',
'#FD89DD',
'#FD61D1',
'#FC3AC6',
'#CA2E9E',
'#972377',
'#65174F',
'#320C28',
'#FFF5EF',
'#FEE6D6',
'#FDCDAD',
'#FCB483',
'#FB9B5A',
'#FA8231',
'#E1752C',
'#C86827',
'#964E1D',
'#4B270F',
'#F3ECFA',
'#E5D4F5',
'#CBA8EB',
'#B17DE1',
'#9751D7',
'#7D26CD',
'#641EA4',
'#4B177B',
'#320F52',
'#190829',
'#EDF9FF',
'#D7F2FF',
'#AFE5FF',
'#86D9FF',
'#5ECCFF',
'#36BFFF',
'#2B99CC',
'#207399',
'#164C66',
'#0B2633',
'#fffbf2',
'#fff0d1',
'#fee5b0',
'#fdd889',
'#fdcb61',
'#fcbe3a',
'#ca982e',
'#977223',
'#654c17',
'#32260c',
],
dark: [],
}
// convert string into a unique color
export const stringToColour = function (str: string) {
let i
export const stringToColor = (input: string, colorArray = designSystem.light) => {
// Calculate a numeric hash value from the input string
let hash = 0
for (i = 0; i < str?.length ?? 0; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash)
}
let colour = '#'
for (i = 0; i < 3; i++) {
const value = (hash >> (i * 8)) & 0xff
colour += `00${value.toString(16)}`.substr(-2)
for (let i = 0; i < input.length; i++) {
hash = input.charCodeAt(i) + ((hash << 5) - hash)
}
return colour
// Ensure the hash value is within the array length
const index = Math.abs(hash) % colorArray.length
// Return the selected color
return colorArray[index]
}
// Function to convert hex color to RGB
function hexToRGBObject(hexColor: string) {
// Remove '#' if present in the hexColor
hexColor = hexColor.replace(/^#/, '')
// Split the hexColor into red, green, and blue components
const r = parseInt(hexColor.substring(0, 2), 16)
const g = parseInt(hexColor.substring(2, 4), 16)
const b = parseInt(hexColor.substring(4, 6), 16)
return { r, g, b }
}
export function isColorDark(hexColor: string) {
const rgbColor = hexToRGBObject(hexColor)
const luminance = 0.299 * rgbColor.r + 0.587 * rgbColor.g + 0.114 * rgbColor.b
// Choose a luminance threshold (e.g., 0.5) to determine darkness/lightness
return luminance < 128
}

24
packages/nc-gui/utils/iconUtils.ts

@ -13,7 +13,6 @@ import MdiThumbUp from '~icons/mdi/thumb-up'
import MdiThumbUpOutline from '~icons/mdi/thumb-up-outline'
import MdiFlag from '~icons/mdi/flag'
import MdiFlagOutline from '~icons/mdi/flag-outline'
import MdiTable from '~icons/mdi/table'
import MsMove from '~icons/material-symbols/drive-file-move-outline'
import MSCloseRounded from '~icons/material-symbols/close-rounded'
import MdiTableLarge from '~icons/mdi/table-large'
@ -92,11 +91,12 @@ import Record from '~icons/nc-icons/record'
import Project from '~icons/nc-icons/project'
// Roles
import MaterialSymbolsManageAccountsOutline from '~icons/material-symbols/manage-accounts-outline'
// account
import MdiCommentAccountOutline from '~icons/mdi/comment-account-outline'
import MaterialSymbolsPersonSearchOutline from '~icons/material-symbols/person-search-outline'
import MaterialSymbolsBlock from '~icons/material-symbols/block'
import Owner from '~icons/nc-icons/owner'
import Creator from '~icons/nc-icons/creator'
import Editor from '~icons/nc-icons/editor'
import Commentor from '~icons/nc-icons/commentor'
import Viewer from '~icons/nc-icons/viewer'
import NoAccess from '~icons/nc-icons/no-access'
// keep it for reference
// todo: remove it after all icons are migrated
@ -433,12 +433,12 @@ export const iconMap = {
magic1: MdiMagicStaff,
workspace: h('span', { class: 'material-symbols' }, 'dataset'),
notification: NcNotification,
role_owner: MaterialSymbolsManageAccountsOutline,
role_creator: MaterialSymbolsManageAccountsOutline,
role_editor: h('span', { class: 'material-symbols' }, 'person'),
role_commenter: MdiCommentAccountOutline,
role_viewer: MaterialSymbolsPersonSearchOutline,
role_no_access: MaterialSymbolsBlock,
role_owner: Owner,
role_creator: Creator,
role_editor: Editor,
role_commenter: Commentor,
role_viewer: Viewer,
role_no_access: NoAccess,
commentHere: NcCommentHere,
}

2
packages/nc-gui/windi.config.ts

@ -95,7 +95,7 @@ export default defineConfig({
200: '#ADC2FF',
300: '#85A3FF',
400: '#5C85FF',
500: '#36F',
500: '#3366FF',
600: '#2952CC',
700: '#1F3D99',
800: '#142966',

2
packages/nocodb/src/models/BaseUser.ts

@ -95,9 +95,9 @@ export default class BaseUser {
`${MetaTable.USERS}.email`,
`${MetaTable.USERS}.invite_token`,
`${MetaTable.USERS}.roles as main_roles`,
`${MetaTable.USERS}.created_at as created_at`,
`${MetaTable.PROJECT_USERS}.base_id`,
`${MetaTable.PROJECT_USERS}.roles as roles`,
`${MetaTable.PROJECT_USERS}.created_at as created_at`,
)
.offset(offset)
.limit(limit);

Loading…
Cancel
Save