diff --git a/package.json b/package.json index 1e1cda64e5..bb2f06e30d 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "@vue/composition-api": "^0.5.0", "axios": "^0.19.2", "base-64": "^0.1.0", + "bytes": "^3.1.0", "cropperjs": "^1.5.6", "date-fns": "^2.14.0", "diff": "^4.0.2", @@ -35,7 +36,6 @@ "nanoid": "^3.1.9", "pinia": "0.0.5", "portal-vue": "^2.1.7", - "pretty-bytes": "^5.3.0", "resize-observer": "^1.0.0", "semver": "^7.3.2", "stylelint-config-prettier": "^8.0.1", @@ -58,6 +58,7 @@ "@storybook/core": "^5.3.18", "@storybook/vue": "^5.3.18", "@types/base-64": "^0.1.3", + "@types/bytes": "^3.1.0", "@types/diff": "^4.0.2", "@types/jest": "^25.2.3", "@types/marked": "^0.7.4", diff --git a/src/assets/avatar-placeholder.svg b/src/assets/avatar-placeholder.svg index 3ac7176f87..2819385cdd 100644 --- a/src/assets/avatar-placeholder.svg +++ b/src/assets/avatar-placeholder.svg @@ -1,7 +1,7 @@ - + diff --git a/src/components/v-avatar/v-avatar.vue b/src/components/v-avatar/v-avatar.vue index 0d086aca67..ba7e405af7 100644 --- a/src/components/v-avatar/v-avatar.vue +++ b/src/components/v-avatar/v-avatar.vue @@ -29,7 +29,7 @@ export default defineComponent({ @@ -43,7 +43,7 @@ body { width: var(--v-avatar-size); height: var(--v-avatar-size); overflow: hidden; - color: var(--white); + color: var(--foreground-subdued); white-space: nowrap; text-overflow: ellipsis; background-color: var(--v-avatar-color); diff --git a/src/components/v-checkbox/v-checkbox.vue b/src/components/v-checkbox/v-checkbox.vue index 3f53ce86c4..7fe03cea95 100644 --- a/src/components/v-checkbox/v-checkbox.vue +++ b/src/components/v-checkbox/v-checkbox.vue @@ -133,6 +133,8 @@ body { .label:not(:empty) { margin-left: 8px; + color: var(--foreground-subdued); + transition: color var(--fast) var(--transition); input { width: 100%; @@ -147,6 +149,8 @@ body { & .checkbox { --v-icon-color: var(--foreground-subdued); + + transition: color var(--fast) var(--transition); } &:disabled { @@ -163,7 +167,10 @@ body { &:not(:disabled):hover { .checkbox { - --v-icon-color: var(--foreground-subdued); + --v-icon-color: var(--foreground-normal); + } + .label { + color: var(--foreground-normal); } } diff --git a/src/displays/filesize/handler.ts b/src/displays/filesize/handler.ts index 153b3090b8..fad4f0461d 100644 --- a/src/displays/filesize/handler.ts +++ b/src/displays/filesize/handler.ts @@ -1,5 +1,5 @@ -import prettyBytes from 'pretty-bytes'; +import bytes from 'bytes'; export default function handler(value: number) { - return prettyBytes(value); + return bytes(value, { decimalPlaces: 0 }); } diff --git a/src/displays/formatted-text/index.ts b/src/displays/formatted-text/index.ts index 042b30f839..eef322edfb 100644 --- a/src/displays/formatted-text/index.ts +++ b/src/displays/formatted-text/index.ts @@ -26,10 +26,10 @@ export default defineDisplay(({ i18n }) => ({ width: 'half', interface: 'dropdown', options: { - items: [ - { itemText: i18n.t('sans_serif'), itemValue: 'sans-serif' }, - { itemText: i18n.t('serif'), itemValue: 'serif' }, - { itemText: i18n.t('monospace'), itemValue: 'monospace' }, + choices: [ + { text: i18n.t('sans_serif'), value: 'sans-serif' }, + { text: i18n.t('serif'), value: 'serif' }, + { text: i18n.t('monospace'), value: 'monospace' }, ], }, }, diff --git a/src/displays/template/index.ts b/src/displays/template/index.ts index e853253597..7ac69d4e06 100644 --- a/src/displays/template/index.ts +++ b/src/displays/template/index.ts @@ -18,7 +18,7 @@ export default defineDisplay(({ i18n }) => ({ options: [ { field: 'template', - name: i18n.t('template'), + name: i18n.t('display_template'), interface: 'text-input', width: 'full', }, diff --git a/src/interfaces/dropdown/dropdown.vue b/src/interfaces/dropdown/dropdown.vue index f24775e7d0..5a7685a783 100644 --- a/src/interfaces/dropdown/dropdown.vue +++ b/src/interfaces/dropdown/dropdown.vue @@ -20,6 +20,7 @@
+
{ if (file.value === null) return null; + if (file.value.type.includes('svg')) return file.value.data.asset_url; if (file.value.type.includes('image') === false) return null; return file.value.data.thumbnails?.find((thumb) => thumb.key === 'directus-small-crop') ?.url; @@ -291,9 +299,24 @@ export default defineComponent({ background-color: var(--background-normal); border-radius: var(--border-radius); + img { + width: 100%; + height: 100%; + object-fit: cover; + } + &.has-file { background-color: var(--primary-alt); } + + &.is-svg { + padding: 4px; + background-color: var(--background-normal); + + img { + object-fit: contain; + } + } } .extension { diff --git a/src/interfaces/image/image.vue b/src/interfaces/image/image.vue index 6d7a6ed030..3648ba2beb 100644 --- a/src/interfaces/image/image.vue +++ b/src/interfaces/image/image.vue @@ -6,7 +6,11 @@ {{ $t('disabled') }} -
+
@@ -217,9 +221,9 @@ img { object-fit: cover; } -.isSVG { +.is-svg { padding: 32px; - background-color: var(--background-subdued); + background-color: var(--background-normal); img { object-fit: contain; diff --git a/src/interfaces/text-input/index.ts b/src/interfaces/text-input/index.ts index f83de6bb1c..3deea22383 100644 --- a/src/interfaces/text-input/index.ts +++ b/src/interfaces/text-input/index.ts @@ -3,7 +3,7 @@ import { defineInterface } from '@/interfaces/define'; export default defineInterface(({ i18n }) => ({ id: 'text-input', - name: i18n.t('interfaces.text-input.text-input'), + name: i18n.t('text_input'), icon: 'text_fields', component: InterfaceTextInput, options: [ @@ -25,22 +25,17 @@ export default defineInterface(({ i18n }) => ({ width: 'half', interface: 'icon', }, - { - field: 'trim', - name: 'Trim', - width: 'half', - interface: 'toggle', - }, { field: 'font', name: 'Font', width: 'half', - interface: 'select-one-dropdown', + interface: 'dropdown', + default: 'sans-serif', options: { - items: [ - { itemText: 'Sans', itemValue: 'sans-serif' }, - { itemText: 'Mono', itemValue: 'monospace' }, - { itemText: 'Serif', itemValue: 'serif' }, + choices: [ + { text: 'Sans Serif', value: 'sans-serif' }, + { text: 'Monospace', value: 'monospace' }, + { text: 'Serif', value: 'serif' }, ], }, }, diff --git a/src/interfaces/text-input/text-input.vue b/src/interfaces/text-input/text-input.vue index 6944de7c3e..da8dda915a 100644 --- a/src/interfaces/text-input/text-input.vue +++ b/src/interfaces/text-input/text-input.vue @@ -3,7 +3,6 @@ :value="value" :placeholder="placeholder" :disabled="disabled" - :trim="trim" :type="masked ? 'password' : 'text'" :class="font" :maxlength="length" diff --git a/src/lang/en-US/index.json b/src/lang/en-US/index.json index 09087d9074..0f24b86eab 100644 --- a/src/lang/en-US/index.json +++ b/src/lang/en-US/index.json @@ -64,7 +64,7 @@ "clear_value": "Clear value", "reset_to_default": "Reset to default", "undo_changes": "Undo changes", - "collapse_sidebar": "Collapse Sidebar", + "page_info": "Page Information", "notifications": "Notifications", "show_all_activity": "Show All Activity", "page_not_found": "Page Not Found", @@ -209,6 +209,7 @@ "no_items": "No items", "disabled": "Disabled", + "information": "Information", "interface_not_found": "Interface \"{interface}\" not found", @@ -221,6 +222,7 @@ "no_collections_copy_admin": "It looks like you don’t have any Collections yet. Fortunately, it’s very easy to create one — click the button below to get started.", "no_collections_copy": "It looks like you don’t have any Collections yet. Please contact your system administrator to have them create your data-model.", + "text_input": "Text Input", "radio_buttons": "Radio Buttons", "checkboxes": "Checkboxes", @@ -576,6 +578,23 @@ "layout_preview": "Layout Preview", "layout_setup": "Layout Setup", + "page_help_collections_overview": "Provides a listing of all collections you have access to.", + "page_help_collections_browse": "**Item Browse Page** — Customize the layout, filters, and sorting to tailor your view of items within this {collection} collection.

You can also save bookmarks of these different configurations to quickly switch between them.

Learn More", + "page_help_collections_detail": "For more information this page please refer to the

Learn More", + "page_help_activity_detail": "For more information this page please refer to the

Learn More", + "page_help_activity_browse": "For more information this page please refer to the

Learn More", + "page_help_files_browse": "For more information this page please refer to the

Learn More", + "page_help_settings_global": "For more information this page please refer to the

Learn More", + "page_help_settings_datamodel_collections": "For more information this page please refer to the

Learn More", + "page_help_settings_datamodel_fields": "For more information this page please refer to the

Learn More", + "page_help_settings_roles_browse": "For more information this page please refer to the

Learn More", + "page_help_settings_roles_detail": "For more information this page please refer to the

Learn More", + "page_help_settings_presets_browse": "For more information this page please refer to the

Learn More", + "page_help_settings_presets_detail": "For more information this page please refer to the

Learn More", + "page_help_settings_webhooks_browse": "For more information this page please refer to the

Learn More", + "page_help_settings_webhooks_detail": "For more information this page please refer to the

Learn More", + "page_help_users_browse": "For more information this page please refer to the

Learn More", + "about_directus": "About Directus", "activity_log": "Activity Log", "add_field_filter": "Add a field filter", @@ -747,7 +766,7 @@ "enter_collection_name": "Enter collection name...", "enter_otp": "Please enter the one-time-password (OTP) from your authenticator app.", "enter_role_name": "Enter role name...", - "enter_value": "Enter Value", + "enter_value": "Enter value...", "environment": "Environment", "equal_to": "Equal to", "error_unknown": "Unknown error. Try again later.", @@ -809,6 +828,7 @@ "hidden_browse": "Hidden on Browse", "hidden_detail": "Hidden on Detail", "icon": "Icon", + "image": "Image", "in_list": "One of these", "info": "Info", "initial_schema": "Choose an Initial Schema", @@ -948,6 +968,7 @@ "sort_direction": "Sort Direction", "spacing": "Spacing", "statuses": "Statuses", + "template": "Template", "text": "Text", "translation": "Translation", "translated_field_name": "Translated field name...", diff --git a/src/layouts/cards/components/card.vue b/src/layouts/cards/components/card.vue index 80c09124e2..8a32900a3e 100644 --- a/src/layouts/cards/components/card.vue +++ b/src/layouts/cards/components/card.vue @@ -279,10 +279,6 @@ export default defineComponent({ line-height: 1.3em; white-space: nowrap; text-overflow: ellipsis; - - > .render-template ::v-deep > *:not(:last-child) { - margin-right: 4px; - } } .title { diff --git a/src/modules/activity/routes/browse/browse.vue b/src/modules/activity/routes/browse/browse.vue index 265f313ec0..59ca373466 100644 --- a/src/modules/activity/routes/browse/browse.vue +++ b/src/modules/activity/routes/browse/browse.vue @@ -6,8 +6,6 @@ - - @@ -20,6 +18,19 @@ :view-query.sync="viewQuery" :detail-route="'/{{project}}/activity/{{primaryKey}}'" /> + + @@ -30,6 +41,7 @@ import useProjectsStore from '@/stores/projects'; import { i18n } from '@/lang'; import { LayoutComponent } from '@/layouts/types'; import useCollectionPreset from '@/composables/use-collection-preset'; +import marked from 'marked'; type Item = { [field: string]: any; @@ -51,6 +63,7 @@ export default defineComponent({ layout, viewOptions, viewQuery, + marked, }; function useBreadcrumb() { diff --git a/src/modules/activity/routes/detail/detail.vue b/src/modules/activity/routes/detail/detail.vue index 013a37546e..88e5cee036 100644 --- a/src/modules/activity/routes/detail/detail.vue +++ b/src/modules/activity/routes/detail/detail.vue @@ -20,6 +20,18 @@ :initial-values="item" :primary-key="primaryKey" /> + + @@ -30,6 +42,7 @@ import ActivityNavigation from '../../components/navigation/'; import { i18n } from '@/lang'; import useItem from '@/composables/use-item'; import SaveOptions from '@/views/private/components/save-options'; +import marked from 'marked'; type Values = { [field: string]: any; @@ -57,6 +70,7 @@ export default defineComponent({ loading, error, breadcrumb, + marked, }; function useBreadcrumb() { diff --git a/src/modules/collections/routes/browse/browse.vue b/src/modules/collections/routes/browse/browse.vue index a5bf06ca5f..93049ca1b6 100644 --- a/src/modules/collections/routes/browse/browse.vue +++ b/src/modules/collections/routes/browse/browse.vue @@ -38,11 +38,6 @@ - - @@ -112,6 +107,26 @@ :filters.sync="filters" :search-query.sync="searchQuery" /> + + @@ -132,6 +147,7 @@ import SearchInput from '@/views/private/components/search-input'; import BookmarkAdd from '@/views/private/components/bookmark-add'; import BookmarkEdit from '@/views/private/components/bookmark-edit'; import router from '@/router'; +import marked from 'marked'; const redirectIfNeeded: NavigationGuard = async (to, from, next) => { const collectionsStore = useCollectionsStore(); @@ -250,6 +266,7 @@ export default defineComponent({ editingBookmark, editBookmark, breadcrumb, + marked, }; function useBreadcrumb() { diff --git a/src/modules/collections/routes/detail/detail.vue b/src/modules/collections/routes/detail/detail.vue index 0827eeb7dd..0f7b863a7a 100644 --- a/src/modules/collections/routes/detail/detail.vue +++ b/src/modules/collections/routes/detail/detail.vue @@ -143,6 +143,9 @@ /> @@ -171,6 +180,7 @@ import CommentsDrawerDetail from '@/views/private/components/comments-drawer-det import useItem from '@/composables/use-item'; import SaveOptions from '@/views/private/components/save-options'; import i18n from '@/lang'; +import marked from 'marked'; type Values = { [field: string]: any; @@ -275,6 +285,7 @@ export default defineComponent({ breadcrumb, title, revisionsDrawerDetail, + marked, refresh, }; diff --git a/src/modules/collections/routes/overview/overview.vue b/src/modules/collections/routes/overview/overview.vue index 5dbbf601d1..9cb0b4508b 100644 --- a/src/modules/collections/routes/overview/overview.vue +++ b/src/modules/collections/routes/overview/overview.vue @@ -32,6 +32,21 @@ {{ $t('no_collections_copy') }} + + @@ -43,6 +58,7 @@ import useNavigation, { NavItem } from '../../composables/use-navigation'; import router from '@/router'; import useUserStore from '@/stores/user'; import useProjectsStore from '@/stores/projects'; +import marked from 'marked'; export default defineComponent({ name: 'collections-overview', @@ -80,7 +96,14 @@ export default defineComponent({ return `/${projectsStore.state.currentProjectKey}/settings/data-model`; }); - return { tableHeaders, navItems, navigateToCollection, isAdmin, dataModelLink }; + return { + tableHeaders, + navItems, + navigateToCollection, + isAdmin, + dataModelLink, + marked, + }; function navigateToCollection(navItem: NavItem) { router.push(navItem.to); diff --git a/src/modules/files/routes/browse/browse.vue b/src/modules/files/routes/browse/browse.vue index 3395f741f5..6c96c9b1c4 100644 --- a/src/modules/files/routes/browse/browse.vue +++ b/src/modules/files/routes/browse/browse.vue @@ -6,11 +6,6 @@ - - @@ -67,6 +62,20 @@ @update:filters="filters = $event" :detail-route="'/{{project}}/files/{{primaryKey}}'" /> + + @@ -82,6 +91,7 @@ import FilterDrawerDetail from '@/views/private/components/filter-drawer-detail' import LayoutDrawerDetail from '@/views/private/components/layout-drawer-detail'; import AddFolder from '../../components/add-folder'; import SearchInput from '@/views/private/components/search-input'; +import marked from 'marked'; type Item = { [field: string]: any; @@ -164,6 +174,7 @@ export default defineComponent({ currentFolder, filtersWithFolderAndType, searchQuery, + marked, }; function useBatchDelete() { diff --git a/src/modules/files/routes/detail/components/file-info-drawer-detail.vue b/src/modules/files/routes/detail/components/file-info-drawer-detail.vue index 42915cc95b..7cf9d1e84a 100644 --- a/src/modules/files/routes/detail/components/file-info-drawer-detail.vue +++ b/src/modules/files/routes/detail/components/file-info-drawer-detail.vue @@ -1,5 +1,5 @@
@@ -86,7 +86,7 @@ export default defineComponent({ type: field.type, }; }) - .map((p) => (typeof p === 'string' ? p.trim() : p)) + .map((p) => p) .filter((p) => p) ); @@ -99,16 +99,31 @@ export default defineComponent({ @import '@/styles/mixins/no-wrap'; .render-template { - display: flex; - align-items: center; + position: relative; max-width: 100%; height: 100%; + padding-right: 8px; & > * { - margin-right: 6px; - - @include no-wrap; + vertical-align: middle; } + + &::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + width: 8px; + background: linear-gradient( + 90deg, + rgba(var(--background-page-rgb), 0) 0%, + rgba(var(--background-page-rgb), 1) 100% + ); + content: ''; + pointer-events: none; + } + + @include no-wrap; } .subdued { diff --git a/src/views/private/components/user-popover/user-popover.vue b/src/views/private/components/user-popover/user-popover.vue index c17facb774..edcec595bc 100644 --- a/src/views/private/components/user-popover/user-popover.vue +++ b/src/views/private/components/user-popover/user-popover.vue @@ -121,17 +121,28 @@ export default defineComponent({ .user-box { display: flex; + min-width: 300px; height: 80px; - margin: 10px 6px; + margin: 8px 4px; .v-avatar { margin-right: 16px; } .status-role { + text-transform: capitalize; + &.invited { + color: var(--primary); + } &.active { color: var(--success); } + &.suspended { + color: var(--warning); + } + &.deleted { + color: var(--danger); + } } .email { @@ -153,7 +164,7 @@ export default defineComponent({ display: flex; align-items: center; height: 80px; - margin: 10px 6px; + margin: 8px 4px; .avatar { width: 80px; diff --git a/src/views/private/private-view.vue b/src/views/private/private-view.vue index 864acdef29..6e0c3ea950 100644 --- a/src/views/private/private-view.vue +++ b/src/views/private/private-view.vue @@ -40,14 +40,6 @@ :class="{ 'is-open': drawerOpen }" @click="drawerOpen = true" > - - {{ $t('collapse_sidebar') }} - - diff --git a/yarn.lock b/yarn.lock index 11509befe4..01bd5a67a9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1904,6 +1904,11 @@ resolved "https://registry.yarnpkg.com/@types/base-64/-/base-64-0.1.3.tgz#875320c0d019f576a179324124cdbd5031a411f5" integrity sha512-DJpw7RKNMXygZ0j2xe6ROBqiJUy7JWEItkzOPBzrT35HUWS7VLYyW9XJX8yCCvE2xg8QD7wesvVyXFg8AVHTMA== +"@types/bytes@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/bytes/-/bytes-3.1.0.tgz#835a3e4aea3b4d7604aca216a78de372bff3ecc3" + integrity sha512-5YG1AiIC8HPPXRvYAIa7ehK3YMAwd0DWiPCtpuL9sgKceWLyWsVtLRA+lT4NkoanDNF9slwQ66lPizWDpgRlWA== + "@types/color-name@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" @@ -4026,7 +4031,7 @@ bytes@3.0.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= -bytes@3.1.0: +bytes@3.1.0, bytes@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== @@ -11694,11 +11699,6 @@ prettier@^2.0.5: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4" integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg== -pretty-bytes@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2" - integrity sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg== - pretty-error@^2.0.2, pretty-error@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3"