diff --git a/assets/img/bg_login.png b/assets/img/bg_login.png new file mode 100644 index 0000000..54ab4bf Binary files /dev/null and b/assets/img/bg_login.png differ diff --git a/assets/img/flex-type.svg b/assets/img/flex-type.svg new file mode 100644 index 0000000..bf5e620 --- /dev/null +++ b/assets/img/flex-type.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/img/osw-type.svg b/assets/img/osw-type.svg new file mode 100644 index 0000000..714591d --- /dev/null +++ b/assets/img/osw-type.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/img/pathways-type.svg b/assets/img/pathways-type.svg new file mode 100644 index 0000000..2edfaa0 --- /dev/null +++ b/assets/img/pathways-type.svg @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/img/tdei-logo.png b/assets/img/tdei-logo.png new file mode 100644 index 0000000..b33898b Binary files /dev/null and b/assets/img/tdei-logo.png differ diff --git a/assets/scss/main.scss b/assets/scss/main.scss index 46b42c0..3b1e1db 100644 --- a/assets/scss/main.scss +++ b/assets/scss/main.scss @@ -1,9 +1,29 @@ @import "theme.scss"; @import "bootstrap/scss/bootstrap.scss"; + +input:-webkit-autofill, +input:-webkit-autofill:hover, +input:-webkit-autofill:focus { + transition: background-color 600000s, color 600000s; +} @import "maplibre-gl/dist/maplibre-gl.css"; @import "vue3-toastify/dist/index.css"; :root { + --primary-font-family: "Open Sans", sans-serif; + --secondary-font-family: "Montserrat", sans-serif; + --brand-primary: #32006e; + --brand-accent: #4b2e83; + --primary-color: var(--brand-primary); + --primary-color-dark: var(--brand-accent); + --secondary-color: #5f647a; + --tdei-blue: #586AB5; + --tdei-green: #479FA1; + --tdei-cyan: #59c3c8; + --purple-background-light: #f4f0fb; + --purple-background-dark: #ddd2ee; + --purple-background-medium: #ebe4f6; + --white: #ffffff; --ws-create-color: $review-create-color; --ws-modify-color: $review-modify-color; --ws-delete-color: $review-delete-color; @@ -14,6 +34,14 @@ html, body, #__nuxt { height: 100%; } +body { + margin: 0; + font-family: var(--primary-font-family); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + min-height: 100vh; +} + /* Vue page transitions */ .fade-enter-active, .fade-leave-active, .layout-enter-active, .layout-leave-active, @@ -47,6 +75,13 @@ label > .form-select:first-child { box-shadow: $box-shadow; } +.dropdown-item.active, +.dropdown-item:active { + color: #2f3661; + text-decoration: none; + background-color: #e2f0f8; +} + /* Review */ .bg-create { @@ -67,3 +102,322 @@ label > .form-select:first-child { .text-delete { color: #{darken($review-delete-color, 3%)}; } + +/* TDEI Utility Classes */ + +.tdei-primary-button { + background-color: var(--primary-color); + border-color: var(--primary-color); + color: #fff; + font-weight: 600; + border-radius: 4px; + + &:hover, + &:active { + background-color: var(--primary-color-dark); + border-color: var(--primary-color-dark); + color: #fff; + } + + &:focus { + background-color: var(--primary-color); + border-color: var(--primary-color); + box-shadow: 0 0 0 0.25rem rgba(50, 0, 110, 0.25); + } + + &:disabled { + background-color: #cccccc; + border-color: #cccccc; + color: #ffffff; + cursor: not-allowed; + } +} + +.tdei-secondary-button { + border-color: var(--secondary-color); + font-weight: 600 !important; + + &:hover { + background-color: var(--secondary-color); + color: #fff; + border-color: var(--secondary-color); + } +} + +.btn-check:checked + .tdei-secondary-button, +.btn-check:active + .tdei-secondary-button, +.tdei-secondary-button.active, +.tdei-secondary-button:active { + background-color: var(--secondary-color); + color: #fff; + border-color: var(--secondary-color); +} + +.tdei-primary-link { + color: var(--primary-color); + font-weight: 600; + text-decoration: none; + + &:hover { + color: var(--primary-color-dark); + text-decoration: underline; + } +} + +.page-header-title { + font-family: var(--secondary-font-family); + font-size: 24px; + font-weight: 700; + margin-bottom: 5px; +} + +.page-header-subtitle { + font-family: var(--secondary-font-family); + font-size: 14px; + color: var(--secondary-color); +} + +.tdei-bold-name { + font-size: 16px; + font-weight: 700; + margin-bottom: 8px; +} + +.tdei-name-desc { + font-size: 14px; + color: var(--secondary-color); +} + +.tdei-hint-text { + font-size: 14px; + color: var(--secondary-color); + font-style: italic; +} + +.apiKey { + border-top: 1px dashed #b5b5b5; + margin-top: 10px; + padding-top: 10px; +} + +.jsonContent { + border: 1px solid var(--secondary-color); + margin-top: 1%; + overflow: auto; +} + +.header { + display: flex; + justify-content: space-between; + align-items: center; + padding-bottom: 20px; +} + +.tdei-outline-cyan-button { + color: var(--tdei-cyan); + font-weight: 600; + border: 2px solid var(--tdei-cyan); + + &:hover, + &:active { + color: #fff; + background-color: var(--tdei-cyan); + border-color: var(--tdei-cyan); + } + + &:focus, + &:focus-visible { + color: var(--tdei-cyan); + border-color: var(--tdei-cyan); + box-shadow: 0 0 0 0.25rem rgba(89, 195, 200, 0.25); + } + + &:disabled { + color: #9aa0b3; + border-color: #d3d7e2; + background-color: transparent; + cursor: not-allowed; + } +} + +.btn.tdei-rounded-button { + background-color: var(--primary-color); + border-color: var(--primary-color); + color: #fff; + font-weight: 600; + border-radius: 100px; + + &:hover, + &:active { + background-color: var(--primary-color-dark); + border-color: var(--primary-color-dark); + color: #fff; + } +} + +.nav-tabs .nav-link { + color: var(--secondary-color); + background-color: transparent !important; + border-top: none !important; + border-left: none !important; + border-right: none !important; + padding: 10px 0; + margin-right: 15px; +} + +.nav-tabs .nav-link:hover { + color: gray; + border: none; +} + +.nav-tabs .nav-link.active { + color: #162848; + background-color: #fff; + font-weight: 600; + border-top: none; + border-left: none; + border-right: none; + border-bottom: 4px solid var(--primary-color); +} + +.maroon-bg, +.maroon-bg:hover { + background-color: #c84349 !important; + border-color: #c84349 !important; + color: #fff !important; + font-weight: 600; + border-radius: 100px; +} + +.form-group-custom { + position: relative; + min-height: 90px; + margin-right: 1rem; +} + +.form-group-custom .form-control, +.form-group-custom .react-datepicker-wrapper, +.form-group-custom .react-select-container { + width: 100%; +} + +.form-group-custom .invalid-feedback { + position: absolute; + bottom: 0; + left: 0; + width: 100%; +} + +.container { + padding: 20px; +} + +.column-style { + background: #FFFFFF 0% 0% no-repeat padding-box; + box-shadow: 0px 1px 12px #0000000D; + border: 1px solid #EEEEEE; + border-radius: 8px; + opacity: 1; + padding: 20px; + flex: 1; + margin-right: 15px; + + &:nth-last-child(1) { + margin-right: 0; + } +} + +.section-style { + background: #FFFFFF 0% 0% no-repeat padding-box; + box-shadow: 0px 1px 12px #0000000D; + border: 1px solid #EEEEEE; + border-radius: 8px; + opacity: 1; + padding: 20px; + margin-top: 20px; +} + +.infoIconImg { + font-size: 14px !important; + color: #a5a5a5 !important; + margin-right: 5px !important; +} + +input[type=checkbox] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + display: inline-block; + border-radius: 6px; + border: 1.5px solid var(--secondary-color); + + &:checked { + background-color: var(--primary-color); + border: 1.5px solid var(--primary-color); + } +} + +.iconImg { + width: 15px; + margin-right: 15px !important; +} + +.formTitle { + margin-bottom: 2px; + font-size: 26px; + font-weight: 300; +} +.MuiStepper-horizontal > .MuiStep-horizontal { + padding-left: 4px; + + .column-style { + flex: unset; + margin-right: 0; + margin-bottom: 20px; + + &:nth-last-child(1) { + margin-bottom: 0; + } + } + + .page-header-title { + font-size: 16px; + } +} + +.form-check-input[type="radio"], +input[type="radio"] { + accent-color: var(--primary-color) !important; +} + +.form-check .form-check-input.form-check-input[type="radio"]:checked { + background-color: var(--primary-color) !important; + border-color: var(--primary-color) !important; +} + +.form-check .form-check-input.form-check-input[type="radio"]:focus { + border-color: var(--primary-color) !important; + box-shadow: 0 0 0 0.25rem rgba(50, 0, 110, 0.25) !important; +} + +.MuiButtonBase-root:focus-visible { + outline: 2px solid #2684ff !important; + outline-offset: 1px; + border-radius: 2px; + box-shadow: none !important; +} + +.btn:focus-visible { + outline: 2px solid #2684ff !important; + outline-offset: 1px; + border-radius: 2px; + box-shadow: none !important; +} + +button:focus-visible, +a:focus-visible { + outline: 2px solid #2684ff !important; + outline-offset: 1px; + border-radius: 2px; + box-shadow: none !important; +} diff --git a/assets/scss/theme.scss b/assets/scss/theme.scss index 5df4fdf..b1fc104 100644 --- a/assets/scss/theme.scss +++ b/assets/scss/theme.scss @@ -3,7 +3,7 @@ /* Bootstrap Customization */ $border-radius: 0.15rem; $card-height: 100%; -$primary: #9b0092; +$primary: #32006e; @import "bootstrap/scss/functions"; @import "bootstrap/scss/variables"; diff --git a/components/AppLogo.vue b/components/AppLogo.vue index 539ca6f..bb905b9 100644 --- a/components/AppLogo.vue +++ b/components/AppLogo.vue @@ -1,4 +1,4 @@ - + diff --git a/components/AppNavbar.vue b/components/AppNavbar.vue index 38106c5..c6174b3 100644 --- a/components/AppNavbar.vue +++ b/components/AppNavbar.vue @@ -1,51 +1,183 @@ - - - + + + - TDEI Workspaces + TDEI Workspaces - - + + - - + + - Home + Home - Dashboard + Dashboard - Create Workspace + Create Workspace - Help + Help - + + + - Sign In - - - {{ auth.displayName }} + + + + {{ auth.displayName }} + + + + + + Dashboard + + + + Logout + + - - Logout - - + + + + + + + + + + + + + + + Home + + + Dashboard + + + Create Workspace + + + Help + + + + {{ auth.displayName }} + + + + + Logout + + + @@ -53,19 +185,316 @@ import { tdeiClient } from '~/services/index' const auth = tdeiClient.auth +const mobileMenuOpen = ref(false) +const isMobileView = ref(false) +const toggleButtonRef = ref(null) +const sideMenuRef = ref(null) + +watch(mobileMenuOpen, (isOpen) => { + if (isOpen) { + nextTick(() => { + sideMenuRef.value?.querySelector('.sideMenuClose')?.focus() + }) + } + else { + toggleButtonRef.value?.focus() + } +}) + +function onKeydown(e: KeyboardEvent) { + if (!mobileMenuOpen.value || !isMobileView.value) return + + if (e.key === 'Escape') { + closeMobileMenu() + return + } + + if (e.key === 'Tab') { + const focusable = Array.from( + sideMenuRef.value?.querySelectorAll( + 'a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])', + ) ?? [], + ) + if (focusable.length === 0) return + const first = focusable.at(0) + const last = focusable.at(-1) + if (!first || !last) return + if (e.shiftKey && document.activeElement === first) { + e.preventDefault() + last.focus() + } + else if (!e.shiftKey && document.activeElement === last) { + e.preventDefault() + first.focus() + } + } +} + +function syncMobileView() { + if (typeof window === 'undefined') { + return + } + + isMobileView.value = window.innerWidth <= 768 + + if (!isMobileView.value) { + mobileMenuOpen.value = false + } +} + +function closeMobileMenu() { + if (isMobileView.value) { + mobileMenuOpen.value = false + } +} + +function logoutFromMobileMenu() { + closeMobileMenu() + auth.clear() + navigateTo('/') +} + +onMounted(() => { + syncMobileView() + window.addEventListener('resize', syncMobileView) + document.addEventListener('keydown', onKeydown) +}) + +onBeforeUnmount(() => { + window.removeEventListener('resize', syncMobileView) + document.removeEventListener('keydown', onKeydown) +}) - diff --git a/components/AppSpinner.vue b/components/AppSpinner.vue index 0c50a4c..f6b7341 100644 --- a/components/AppSpinner.vue +++ b/components/AppSpinner.vue @@ -1,5 +1,8 @@ - + Loading... diff --git a/components/DatasetTypeRadio.vue b/components/DatasetTypeRadio.vue index 1784906..3e4f900 100644 --- a/components/DatasetTypeRadio.vue +++ b/components/DatasetTypeRadio.vue @@ -9,7 +9,7 @@ autocomplete="off" value="osw" > - OpenSidewalks + OpenSidewalks - GTFS Pathways + GTFS Pathways diff --git a/components/SigninForm.vue b/components/SigninForm.vue index 7597d4c..4443b38 100644 --- a/components/SigninForm.vue +++ b/components/SigninForm.vue @@ -1,81 +1,272 @@ - - - TDEI Username - - + + + + + Welcome! + + + Please login to your account. + + + + + TDEI Username + + Enter the same username that you provide to use the TDEI API. - - Password - + + Password + + + + + + - - - Submit + + {{ loading.active ? 'Signing In...' : 'Sign In' }} - {{ error }} + + + {{ error }} + + + diff --git a/components/dashboard/Toolbar.vue b/components/dashboard/Toolbar.vue index 86ed05c..da31865 100644 --- a/components/dashboard/Toolbar.vue +++ b/components/dashboard/Toolbar.vue @@ -3,7 +3,8 @@ @@ -20,13 +21,13 @@ Rapid 3 (beta) - + Edit Tasks --> - + Export - + Settings @@ -100,3 +101,32 @@ function workspacePath(page) { return `/workspace/${props.workspace.id}/${page}`; } + + diff --git a/components/dashboard/WorkspaceItem.vue b/components/dashboard/WorkspaceItem.vue index b6a9b95..e9f9b20 100644 --- a/components/dashboard/WorkspaceItem.vue +++ b/components/dashboard/WorkspaceItem.vue @@ -1,31 +1,39 @@ - - {{ workspace.title }} - - {{ workspace.type }} - - - - - App - - - - {{ ROLE_LABELS.lead }} - - - {{ ROLE_LABELS.validator }} - + + + + + + + + {{ formatTypeLabel(workspace.type) }} + + + {{ workspace.externalAppAccess === 1 ? 'App Public' : 'App Private' }} + + + + {{ ROLE_LABELS.lead }} + + + {{ ROLE_LABELS.validator }} + + + + + {{ workspace.title }} + ID: {{ workspace.id }} + + + + diff --git a/components/review/FilterDropdown.vue b/components/review/FilterDropdown.vue index e3923b9..8d265ac 100644 --- a/components/review/FilterDropdown.vue +++ b/components/review/FilterDropdown.vue @@ -64,7 +64,7 @@ - Apply + Apply diff --git a/components/review/Toolbar.vue b/components/review/Toolbar.vue index 033505a..bbdbae5 100644 --- a/components/review/Toolbar.vue +++ b/components/review/Toolbar.vue @@ -5,7 +5,7 @@ #{{ props.item.id }} Edit Here Save diff --git a/components/settings/panel/Delete.vue b/components/settings/panel/Delete.vue index 189a87d..ae3cdc6 100644 --- a/components/settings/panel/Delete.vue +++ b/components/settings/panel/Delete.vue @@ -21,7 +21,7 @@ @@ -39,7 +39,7 @@ diff --git a/components/settings/panel/General.vue b/components/settings/panel/General.vue index 5ff13a9..bc9edba 100644 --- a/components/settings/panel/General.vue +++ b/components/settings/panel/General.vue @@ -22,7 +22,7 @@ Rename diff --git a/components/settings/panel/Imagery.vue b/components/settings/panel/Imagery.vue index 8178344..f2abaea 100644 --- a/components/settings/panel/Imagery.vue +++ b/components/settings/panel/Imagery.vue @@ -61,7 +61,7 @@ Save diff --git a/components/settings/teams/JoinDialog.vue b/components/settings/teams/JoinDialog.vue index 464f572..b6f7365 100644 --- a/components/settings/teams/JoinDialog.vue +++ b/components/settings/teams/JoinDialog.vue @@ -51,7 +51,7 @@
+ Please login to your account. +