diff --git a/assets/images/utils/align-left.svg b/assets/images/utils/align-left.svg new file mode 100644 index 000000000..e295fc502 --- /dev/null +++ b/assets/images/utils/align-left.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/assets/images/utils/asterisk.svg b/assets/images/utils/asterisk.svg new file mode 100644 index 000000000..19e562fdf --- /dev/null +++ b/assets/images/utils/asterisk.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/assets/images/utils/chevron-left.svg b/assets/images/utils/chevron-left.svg new file mode 100644 index 000000000..2b7022366 --- /dev/null +++ b/assets/images/utils/chevron-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/assets/images/utils/coins.svg b/assets/images/utils/coins.svg new file mode 100644 index 000000000..8d3fd9d2d --- /dev/null +++ b/assets/images/utils/coins.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/assets/images/utils/copyright.svg b/assets/images/utils/copyright.svg new file mode 100644 index 000000000..3a93176c2 --- /dev/null +++ b/assets/images/utils/copyright.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/assets/images/utils/lightbulb.svg b/assets/images/utils/lightbulb.svg new file mode 100644 index 000000000..724bc9776 --- /dev/null +++ b/assets/images/utils/lightbulb.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/assets/images/utils/link.svg b/assets/images/utils/link.svg new file mode 100644 index 000000000..f5db36f31 --- /dev/null +++ b/assets/images/utils/link.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/assets/images/utils/send.svg b/assets/images/utils/send.svg new file mode 100644 index 000000000..e20fad810 --- /dev/null +++ b/assets/images/utils/send.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/assets/images/utils/tag.svg b/assets/images/utils/tag.svg index c6e824cff..d39bfbc02 100644 --- a/assets/images/utils/tag.svg +++ b/assets/images/utils/tag.svg @@ -1,5 +1,5 @@ - - - + + + + + \ No newline at end of file diff --git a/assets/images/utils/tags.svg b/assets/images/utils/tags.svg new file mode 100644 index 000000000..37c752456 --- /dev/null +++ b/assets/images/utils/tags.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/assets/images/utils/user-plus.svg b/assets/images/utils/user-plus.svg new file mode 100644 index 000000000..09e5ff83a --- /dev/null +++ b/assets/images/utils/user-plus.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/assets/images/utils/user-x.svg b/assets/images/utils/user-x.svg new file mode 100644 index 000000000..b8244f0de --- /dev/null +++ b/assets/images/utils/user-x.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/assets/styles/components.scss b/assets/styles/components.scss index d4305c32a..3925608fe 100644 --- a/assets/styles/components.scss +++ b/assets/styles/components.scss @@ -1,3 +1,478 @@ +/* + Base components +*/ + +.multiselect--above .multiselect__content-wrapper { + border-top: none !important; + border-top-left-radius: var(--size-rounded-card) !important; + border-top-right-radius: var(--size-rounded-card) !important; +} + +.known-error .multiselect__tags { + border-color: var(--color-special-red) !important; + background-color: var(--color-warning-bg) !important; + + &::placeholder { + color: var(--color-warning-text); + } +} + +.multiselect { + color: var(--color-text) !important; + outline: 2px solid transparent; + + input { + background: transparent; + box-shadow: none; + } + + input::placeholder { + color: var(--color-text); + } + + .multiselect__tags { + border-radius: var(--size-rounded-sm); + background: var(--color-dropdown-bg); + box-shadow: var(--shadow-inset-sm); + border: none; + cursor: pointer; + padding-left: 7px; + padding-top: 10px; + + transition: background-color 0.1s ease-in-out; + + &:active { + background: var(--color-button-bg-hover); + + .multiselect__spinner { + background: var(--color-button-bg-hover); + } + } + + .multiselect__single { + background: transparent; + } + + .multiselect__tag { + border-radius: var(--size-rounded-sm); + color: var(--color-text-dark); + background: transparent; + border: 2px solid var(--color-brand); + } + + .multiselect__tag-icon { + background: transparent; + + &:after { + color: var(--color-text-dark); + } + } + + .multiselect__placeholder { + color: var(--color-button-text); + margin-left: 8px; + opacity: 0.6; + font-size: 16px; + line-height: 20px; + } + } + + .multiselect__content-wrapper { + background: var(--color-dropdown-bg); + border: none; + overflow-x: hidden; + border-bottom-left-radius: var(--size-rounded-sm); + border-bottom-right-radius: var(--size-rounded-sm); + box-shadow: var(--shadow-inset-sm), var(--shadow-floating); + + .multiselect__element { + .multiselect__option--highlight { + background: var(--color-button-bg-active); + color: var(--color-text-dark); + } + + .multiselect__option--selected { + background: var(--color-brand); + font-weight: bold; + color: var(--color-brand-inverted); + } + } + } + + .multiselect__spinner { + background: var(--color-dropdown-bg); + + &:active { + background: var(--color-button-bg-hover); + } + } + + &.multiselect--disabled { + background: none; + + .multiselect__current, + .multiselect__select { + background: none; + } + } +} + +.grid-display { + display: grid; + grid-gap: var(--spacing-card-md); + grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); + + .grid-display__item { + display: flex; + flex-grow: 1; + flex-direction: column; + justify-content: flex-start; + background-color: var(--color-bg); + border-radius: var(--size-rounded-card); + padding: var(--spacing-card-lg); + gap: var(--spacing-card-md); + + .label { + color: var(--color-heading); + font-weight: bold; + font-size: 1rem; + } + + .value { + color: var(--color-text-dark); + font-weight: bold; + font-size: 2rem; + } + + .goto-link { + margin-top: auto; + } + } + + &.width-12 { + grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); + } + + &.width-16 { + grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); + } +} + +/* + Cards and body styling +*/ +.base-card { + @extend .padding-lg; + + position: relative; + min-height: var(--font-size-2xl); + + background-color: var(--color-raised-bg); + border-radius: var(--size-rounded-card); + + margin-bottom: var(--spacing-card-md); + outline: 2px solid transparent; + + box-shadow: var(--shadow-card); + + .card__overlay { + position: absolute; + top: 1rem; + right: 1rem; + display: flex; + flex-direction: column; + align-items: flex-end; + grid-gap: 0.5rem; + z-index: 2; + } + + &.warning { + border-left: 0.5rem solid var(--color-banner-side); + padding: 1.5rem; + line-height: 1.5; + background-color: var(--color-banner-bg); + color: var(--color-banner-text); + min-height: 0; + + a { + /* Uses active color to increase contrast */ + color: var(--color-link-active); + text-decoration: underline; + } + } +} + +.universal-labels { + label, + .label { + :where(.label__title) { + display: block; + margin-block: var(--spacing-card-md) var(--spacing-card-sm); + + // Same styling as h3 + color: var(--color-text-dark); + font-size: 1.17rem; + font-weight: bold; + + .required { + color: var(--color-special-red); + } + + &.size-card-header { + font-size: var(--font-size-xl); + margin-bottom: 1rem; + } + } + + :where(.label__description) { + display: block; + margin-block-end: var(--spacing-card-sm); + + .label__subdescription { + display: block; + margin-block-start: var(--spacing-card-md); + } + } + + :where(h1, h2, h3, h4) { + margin-block: 0; + } + } +} + +.padding-lg { + padding: var(--spacing-card-lg); +} + +.padding-bg { + padding: var(--spacing-card-bg); +} + +.padding-md { + padding: var(--spacing-card-md); +} + +.padding-sm { + padding: var(--spacing-card-sm); +} + +.padding-0 { + padding: 0; +} + +.padding-block-lg { + padding-block: var(--spacing-card-lg); +} + +.padding-block-bg { + padding-block: var(--spacing-card-bg); +} + +.padding-block-md { + padding-block: var(--spacing-card-md); +} + +.padding-block-sm { + padding-block: var(--spacing-card-sm); +} + +.padding-block-0 { + padding-block: 0; +} + +.padding-inline-lg { + padding-inline: var(--spacing-card-lg); +} + +.padding-inline-bg { + padding-inline: var(--spacing-card-bg); +} + +.padding-inline-md { + padding-inline: var(--spacing-card-md); +} + +.padding-inline-sm { + padding-inline: var(--spacing-card-sm); +} + +.padding-inline-0 { + padding-inline: 0; +} + +.universal-body { + @extend .universal-labels; + + .multiselect { + width: 15rem; + } + + > :where(input + *, .input-group + *, .textarea-wrapper + *, .chips + + *, .resizable-textarea-wrapper + *, .input-div + *) { + margin-block-start: var(--spacing-card-md); + } + + :where(button, .button, .iconified-button) { + width: fit-content; + } + + .input-group { + input { + width: auto; + flex-basis: 0; + } + } + + :where(input) { + box-sizing: border-box; + max-height: 40px; + width: 24rem; + flex-basis: 24rem; + + &:not(.stylized-toggle) { + max-width: 100%; + } + } + + :where(.adjacent-input, &.adjacent-input) { + display: flex; + flex-direction: row; + align-items: center; + flex-wrap: wrap; + gap: var(--spacing-card-sm); + margin-bottom: calc(var(--spacing-card-sm) + var(--spacing-card-md)); + + .iconified-button, + .input-group { + flex-shrink: 0; + } + + input { + flex-shrink: 1; + } + + > :first-child { + flex-shrink: 2; + flex-grow: 1; + flex-basis: min-content; + } + + label, + .label { + .label__title { + margin-block: 0; + } + + .label__description { + margin-block-end: 0; + } + + .label__description:not(:first-child) { + margin-top: var(--spacing-card-sm); + } + } + + @media screen and (max-width: 750px) { + &:not(&.small) { + flex-direction: column; + align-items: start; + + .stylized-toggle { + flex-basis: 0; + } + } + } + } + + h1 { + display: flex; + align-items: center; + } + + > :first-child { + margin-block-start: 0; + } + + > :last-child { + margin-block-end: 0; + } + + :where(.header__row) { + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: var(--spacing-card-sm); + + * { + flex-shrink: 0; + } + + .header__title { + margin: 0; + flex-grow: 1; + } + + &:not(:last-child) { + margin-bottom: var(--spacing-card-md); + } + } + + > .label:first-child :where(> :first-child, .label__title), + > label:first-child :where(> :first-child, .label__title), + > .adjacent-input:first-child :where(> :first-child, .label__title) { + margin-block-start: 0; + } +} + +.universal-card { + @extend .base-card; + @extend .universal-body; +} + +.universal-modal { + @extend .universal-body; + + padding: var(--spacing-card-bg); + display: flex; + flex-direction: column; + + > p:first-child { + margin-top: 0; + } + + @media screen and (max-width: 750px) { + .adjacent-input, + &.adjacent-input &:not(&.small) { + flex-direction: row; + align-items: center; + } + } + + @media screen and (max-width: calc(600px + 2rem)) { + .adjacent-input, + &.adjacent-input &:not(&.small) { + flex-direction: column; + align-items: start; + } + } +} + +.navigation-card { + @extend .base-card; + @extend .padding-inline-lg; + @extend .padding-block-md; + + align-items: center; + display: flex; + justify-content: space-between; + flex-wrap: wrap; + row-gap: 0.5rem; +} + +/* + Other + */ + // Here lies ππ πΈπππππ πΈππππ // which allows to have just one wrapper div .iconified-input { @@ -551,6 +1026,11 @@ tr.button-transparent { --text-color: var(--color-brand-inverted); } +.moderation-button { + --background-color: var(--color-special-orange); + --text-color: var(--color-brand-inverted); +} + .brand-button { --background-color: var(--color-brand); --text-color: var(--color-brand-inverted); @@ -840,22 +1320,23 @@ tr.button-transparent { } .vue-notification { - background: #44a4fc; - border-left: 5px solid #44a4fc; + background: var(--color-special-blue); + border-left: 5px solid var(--color-special-blue); + color: var(--color-brand-inverted); &.success { - background: #68cd86; - border-left-color: #68cd86; + background: var(--color-special-green); + border-left-color: var(--color-special-green); } &.warn { - background: #ffb648; - border-left-color: #ffb648; + background: var(--color-special-orange); + border-left-color: var(--color-special-orange); } &.error { - background: #e54d42; - border-left-color: #e54d42; + background: var(--color-special-red); + border-left-color: var(--color-special-red); } } @@ -977,214 +1458,6 @@ h3 { } } -.base-card { - @extend .padding-lg; - - position: relative; - min-height: var(--font-size-2xl); - - background-color: var(--color-raised-bg); - border-radius: var(--size-rounded-card); - - margin-bottom: var(--spacing-card-md); - outline: 2px solid transparent; - - box-shadow: var(--shadow-card); - - .card__overlay { - position: absolute; - top: 1rem; - right: 1rem; - display: flex; - flex-direction: column; - align-items: flex-end; - grid-gap: 0.5rem; - z-index: 2; - } - - &.warning { - border-left: 0.5rem solid var(--color-banner-side); - padding: 1.5rem; - line-height: 1.5; - background-color: var(--color-banner-bg); - color: var(--color-banner-text); - min-height: 0; - - a { - /* Uses active color to increase contrast */ - color: var(--color-link-active); - text-decoration: underline; - } - } -} - -.universal-labels { - label, - .label { - .label__title { - display: block; - margin-block: var(--spacing-card-md) var(--spacing-card-sm); - - // Same styling as h3 - color: var(--color-text-dark); - font-size: 1.17em; - font-weight: bold; - - .required { - color: var(--color-special-red); - } - } - - .label__description { - display: block; - margin-block-end: var(--spacing-card-sm); - - .label__subdescription { - display: block; - margin-block-start: var(--spacing-card-md); - } - } - } -} - -.padding-lg { - padding: var(--spacing-card-lg); -} - -.padding-bg { - padding: var(--spacing-card-bg); -} - -.padding-md { - padding: var(--spacing-card-md); -} - -.padding-sm { - padding: var(--spacing-card-sm); -} - -.padding-block-lg { - padding-block: var(--spacing-card-lg); -} - -.padding-block-bg { - padding-block: var(--spacing-card-bg); -} - -.padding-block-md { - padding-block: var(--spacing-card-md); -} - -.padding-block-sm { - padding-block: var(--spacing-card-sm); -} - -.padding-inline-lg { - padding-inline: var(--spacing-card-lg); -} - -.padding-inline-bg { - padding-inline: var(--spacing-card-bg); -} - -.padding-inline-md { - padding-inline: var(--spacing-card-md); -} - -.padding-inline-sm { - padding-inline: var(--spacing-card-sm); -} - -.universal-card { - @extend .base-card; - @extend .universal-labels; - - .multiselect { - width: 15rem; - } - - > :where(input + *, .input-group + *) { - margin-block-start: var(--spacing-card-md); - } - - .input-group { - .multiselect, - input { - width: auto; - flex-basis: 0; - } - } - - button, - .button, - .iconified-button { - width: fit-content; - } - - input { - box-sizing: border-box; - max-height: 40px; - width: 24rem; - flex-basis: 24rem; - - &:not(.stylized-toggle) { - max-width: 100%; - } - } - - .adjacent-input, - &.adjacent-input { - display: flex; - flex-direction: row; - align-items: center; - - .iconified-button, - .input-group { - flex-shrink: 0; - } - - input { - flex-shrink: 1; - } - - > :first-child { - flex-shrink: 2; - flex-grow: 1; - margin-right: var(--spacing-card-md); - } - - @media screen and (max-width: 750px) { - &:not(&.small) { - flex-direction: column; - align-items: start; - margin-bottom: var(--spacing-card-sm); - - .stylized-toggle { - flex-basis: 0; - } - - > :first-child { - margin-right: 0; - margin-bottom: var(--spacing-card-md); - } - } - } - } - - h1 { - display: flex; - align-items: center; - } - - > :first-child { - margin-block-start: 0; - } - - > :last-child { - margin-block-end: 0; - } -} - .push-right { margin-left: auto; margin-right: 0; @@ -1206,31 +1479,6 @@ button { } } -.header-card { - @extend .universal-card; - - .header__row { - display: flex; - flex-direction: row; - align-items: center; - flex-wrap: wrap; - gap: var(--spacing-card-sm); - - * { - flex-shrink: 0; - } - - .header__title { - margin: 0; - flex-grow: 1; - } - - &:not(:last-child) { - margin-bottom: var(--spacing-card-md); - } - } -} - .legacy-label-styles { label { display: flex; @@ -1298,6 +1546,32 @@ button { input { flex-shrink: 2; } + + &.shrink-first { + :first-child { + flex-shrink: 2; + flex-grow: 1; + flex-basis: min-content; + } + + :not(:first-child) { + flex-shrink: 1; + } + } +} + +.input-stack { + display: flex; + flex-direction: column; + + > * { + margin-bottom: var(--spacing-card-sm); + } + + > .multiselect { + width: unset; + height: inherit; + } } .text-input-wrapper { @@ -1414,6 +1688,14 @@ button { } } +.wrap-as-needed { + overflow-wrap: break-word; + word-wrap: break-word; + word-break: break-word; + -webkit-hyphens: auto; + hyphens: auto; +} + .sr-only { position: absolute; width: 0; diff --git a/assets/styles/global.scss b/assets/styles/global.scss index 18731680e..9c21ddb6f 100644 --- a/assets/styles/global.scss +++ b/assets/styles/global.scss @@ -76,7 +76,7 @@ html { --color-hr: var(--color-text); --color-table-border: #dfe2e5; - --color-table-alternate-row: #f6f8fa; + --color-table-alternate-row: #f2f4f7; --shadow-inset-lg: inset 0px -2px 2px hsla(221, 39%, 11%, 0.1); --shadow-inset: inset 0px -2px 2px hsla(221, 39%, 11%, 0.05); @@ -204,7 +204,7 @@ html { --color-hr: var(--color-text); --color-table-border: #4f5864; - --color-table-alternate-row: #262a30; + --color-table-alternate-row: #202228; --shadow-inset-lg: inset 0px -2px 2px hsla(221, 39%, 11%, 0.1); --shadow-inset: inset 0px -2px 2px hsla(221, 39%, 11%, 0.05); diff --git a/components/ui/Avatar.vue b/components/ui/Avatar.vue index 0ba0597d8..fc3fb8b27 100644 --- a/components/ui/Avatar.vue +++ b/components/ui/Avatar.vue @@ -2,14 +2,18 @@ diff --git a/components/ui/Badge.vue b/components/ui/Badge.vue index 14f5e12ae..2e8958eda 100644 --- a/components/ui/Badge.vue +++ b/components/ui/Badge.vue @@ -1,28 +1,32 @@ - {{ $capitalizeString(type) }} - Modrinth Team - Moderator + + {{ $capitalizeString(type) }} + + + Modrinth Team + + + Moderator + Creator Listed Unlisted Draft - Archived + + Archived + Rejected - Under review - {{ $capitalizeString(type) }} + + Under review + + Accepted + + Pending + + + {{ $capitalizeString(type) }} + @@ -36,6 +40,7 @@ import DraftIcon from '~/assets/images/utils/file-text.svg?inline' import CrossIcon from '~/assets/images/utils/x.svg?inline' import ArchiveIcon from '~/assets/images/utils/archive.svg?inline' import ProcessingIcon from '~/assets/images/utils/updated.svg?inline' +import CheckIcon from '~/assets/images/utils/check.svg?inline' export default { name: 'Badge', @@ -49,6 +54,7 @@ export default { CrossIcon, ArchiveIcon, ProcessingIcon, + CheckIcon, }, props: { type: { @@ -90,12 +96,14 @@ export default { --badge-color: var(--color-special-red); } + &.type--pending, &.type--moderator, &.type--processing, &.orange { --badge-color: var(--color-special-orange); } + &.type--accepted, &.type--admin, &.green { --badge-color: var(--color-special-green); diff --git a/components/ui/Checkbox.vue b/components/ui/Checkbox.vue index 06b39fe8f..f86a62506 100644 --- a/components/ui/Checkbox.vue +++ b/components/ui/Checkbox.vue @@ -73,7 +73,7 @@ export default { p { user-select: none; - padding: 0.2rem 0rem; + padding: 0.2rem 0; margin: 0; } diff --git a/components/ui/EnvironmentIndicator.vue b/components/ui/EnvironmentIndicator.vue new file mode 100644 index 000000000..d1bece1bf --- /dev/null +++ b/components/ui/EnvironmentIndicator.vue @@ -0,0 +1,116 @@ + + + + A {{ type }} + + + + + Client or server + + + + Client and server + + + + Client + + + + Server + + + + Unsupported + + + + A {{ type }} + + + + + diff --git a/components/ui/FileInput.vue b/components/ui/FileInput.vue index affaad9cc..7c1df921d 100644 --- a/components/ui/FileInput.vue +++ b/components/ui/FileInput.vue @@ -85,7 +85,6 @@ export default { diff --git a/components/ui/NavStackItem.vue b/components/ui/NavStackItem.vue index d9071f74a..48696ac46 100644 --- a/components/ui/NavStackItem.vue +++ b/components/ui/NavStackItem.vue @@ -1,21 +1,44 @@ - + {{ label }} BETA + + + + + {{ label }} + BETA + + + i forgor π @@ -31,12 +62,20 @@ export default { diff --git a/components/ui/ProjectCard.vue b/components/ui/ProjectCard.vue index 66fd077cd..e60dfa780 100644 --- a/components/ui/ProjectCard.vue +++ b/components/ui/ProjectCard.vue @@ -9,7 +9,7 @@ tabindex="-1" :to="`/${$getProjectTypeForUrl(type, categories)}/${id}`" > - + - - - A {{ projectTypeDisplay }} - - - - - Client or server - - - - Client and server - - - - Client - - - - Server - - - - Unsupported - - - - A {{ projectTypeDisplay }} - - + @@ -150,11 +105,8 @@ + + diff --git a/pages/_type/_id.vue b/pages/_type/_id.vue index 0d2dbbec6..648c22f09 100644 --- a/pages/_type/_id.vue +++ b/pages/_type/_id.vue @@ -1,5 +1,111 @@ - + + + + + + + + + + - + - - - - {{ project.title }} + - + + {{ project.title }} + + + + {{ project.description }} + + - - Universal {{ projectTypeDisplay }} + + + + + + + + {{ $formatNumber(project.downloads) }} + + downloads + - - - Client {{ projectTypeDisplay }} + + + + + {{ $formatNumber(project.followers) }} + + followers + - - - Server {{ projectTypeDisplay }} - - - - - {{ project.description }} - - - - - - - - {{ $formatNumber(project.downloads) }} - - downloads - - - - - - - {{ $formatNumber(project.followers) }} - - followers - - - - - - Created - {{ - $dayjs(project.published).fromNow() - }} - - - - Updated - {{ $dayjs(project.updated).fromNow() }} - - - - - - + - - Report - - + Created + {{ + $dayjs(project.published).fromNow() + }} + + - - Follow - - - - Unfollow - - - - - - Report - - - - Follow - - + + Updated + {{ + $dayjs(project.updated).fromNow() + }} + + + + + + + + Report + + + + Follow + + + + Unfollow + + + + + + Report + + + + Follow + + + - Your project is currently not viewable by people who are not part - of your team. Please wait for our moderators to manually review - your project to see if it abides by our - content rules! - - - - Your project is currently not viewable by people who are not part - of your team. If you would like to publish your project, click the - button below to send your project in for review. - @@ -260,14 +336,6 @@ Resubmit for review - - - Submit for review - + - + + + + + Settings + + + img.featured) + }, + }, + watch: { + '$route.path': { + async handler() { + await this.reset() + }, + }, }, methods: { + reset() { + // First time going to settings, this will run, but not subsequent times. + if (!this.isSettings) { + this.from = this.$nuxt.context.from ? this.$nuxt.context.from.name : '' + } + this.routeName = this.$route.name + this.isSettings = this.routeName.startsWith('type-id-settings') + }, async resetProject() { const project = ( await this.$axios.get( @@ -1018,36 +1145,43 @@ export default { async submitForReview() { if ( this.project.body === '' || + this.project.body.startsWith('# Placeholder description') || this.versions.length < 1 || this.project.client_side === 'unknown' || this.project.server_side === 'unknown' ) { this.showKnownErrors = true } else { - this.$nuxt.$loading.start() - - try { - await this.$axios.patch( - `project/${this.project.id}`, - { - status: 'processing', - }, - this.$defaultHeaders() - ) - - this.project.status = 'processing' - } catch (err) { - this.$notify({ - group: 'main', - title: 'An error occurred', - text: err.response.data.description, - type: 'error', - }) - } - - this.$nuxt.$loading.finish() + await this.setProcessing() } }, + toggleChecklistCollapse() { + this.collapsedChecklist = !this.collapsedChecklist + }, + async setProcessing() { + this.$nuxt.$loading.start() + + try { + await this.$axios.patch( + `project/${this.project.id}`, + { + status: 'processing', + }, + this.$defaultHeaders() + ) + + this.project.status = 'processing' + } catch (err) { + this.$notify({ + group: 'main', + title: 'An error occurred', + text: err.response.data.description, + type: 'error', + }) + } + + this.$nuxt.$loading.finish() + }, async getLicenseData() { try { const text = await this.$axios.get( @@ -1060,6 +1194,104 @@ export default { this.$refs.modal_license.show() }, + async patchProject(data, quiet = false) { + let result = false + this.$nuxt.$loading.start() + + try { + await this.$axios.patch( + `project/${this.project.id}`, + data, + this.$defaultHeaders() + ) + + if (this.iconChanged) { + await this.$axios.patch( + `project/${this.project.id}/icon?ext=${ + this.icon.type.split('/')[this.icon.type.split('/').length - 1] + }`, + this.icon, + this.$defaultHeaders() + ) + } + + for (const key in data) { + this.project[key] = data[key] + } + + if (data.license_id) { + this.project.license.id = data.license_id + } + if (data.license_url) { + this.project.license.url = data.license_url + } + + this.$emit('update:project', this.project) + result = true + if (!quiet) { + this.$notify({ + group: 'main', + title: 'Project updated', + text: 'Your project has been updated.', + type: 'success', + }) + window.scrollTo({ top: 0, behavior: 'smooth' }) + } + } catch (err) { + this.$notify({ + group: 'main', + title: 'An error occurred', + text: err.response.data.description, + type: 'error', + }) + window.scrollTo({ top: 0, behavior: 'smooth' }) + } + + this.$nuxt.$loading.finish() + + return result + }, + async patchIcon(icon) { + let result = false + this.$nuxt.$loading.start() + + try { + await this.$axios.patch( + `project/${this.project.id}/icon?ext=${ + icon.type.split('/')[icon.type.split('/').length - 1] + }`, + icon, + this.$defaultHeaders() + ) + await this.updateIcon() + result = true + this.$notify({ + group: 'main', + title: 'Project icon updated', + text: "Your project's icon has been updated.", + type: 'success', + }) + } catch (err) { + this.$notify({ + group: 'main', + title: 'An error occurred', + text: err.response.data.description, + type: 'error', + }) + + window.scrollTo({ top: 0, behavior: 'smooth' }) + } + + this.$nuxt.$loading.finish() + return result + }, + async updateIcon() { + const response = await this.$axios.get( + `project/${this.project.id}`, + this.$defaultHeaders() + ) + this.project.icon_url = response.data.icon_url + }, }, } @@ -1068,23 +1300,13 @@ export default { grid-area: header; .title { overflow-wrap: break-word; - margin: 0.25rem 0; + margin: var(--spacing-card-xs) 0; color: var(--color-text-dark); font-size: var(--font-size-xl); } - .side-descriptor { - display: flex; - align-items: center; - color: var(--color-text-dark); - font-weight: bold; - font-size: var(--font-size-sm); - margin-bottom: 0.5rem; - - svg { - height: 1.25rem; - margin-right: 0.125rem; - } + .status-badge { + margin-top: var(--spacing-card-sm); } .description { @@ -1125,6 +1347,38 @@ export default { } } +.project__header { + overflow: hidden; + .project__gallery { + display: none; + } + &.has-featured-image { + .project__gallery { + display: inline-block; + width: 100%; + height: 10rem; + background-color: var(--color-button-bg-active); + img { + width: 100%; + height: 10rem; + object-fit: cover; + } + } + .project__icon { + margin-top: calc(-3rem - var(--spacing-card-lg) - 4px); + margin-left: -4px; + z-index: 1; + border: 4px solid var(--color-raised-bg); + border-bottom: none; + } + } + .project__header__content { + margin: 0; + background: none; + border-radius: unset; + } +} + .project-info { height: auto; overflow: hidden; @@ -1305,4 +1559,23 @@ export default { .modal-license { padding: var(--spacing-card-bg); } +.settings-header { + display: flex; + flex-direction: row; + gap: var(--spacing-card-sm); + align-items: center; + margin-bottom: var(--spacing-card-bg); + + .settings-header__icon { + flex-shrink: 0; + } + + .settings-header__text { + h1 { + font-size: var(--font-size-md); + margin-top: 0; + margin-bottom: var(--spacing-card-sm); + } + } +} diff --git a/pages/_type/_id/edit.vue b/pages/_type/_id/edit.vue deleted file mode 100644 index 74593b659..000000000 --- a/pages/_type/_id/edit.vue +++ /dev/null @@ -1,1086 +0,0 @@ - - - - - Edit project - - - - Cancel - - - - Save changes - - - - - - Your project must have a name. - - Your project must have a summary. - - - Your project cannot have an empty URL suffix. - - - Your project must have an extended description. - - Your project must have a license. - - - - - - - Name* - - Be creative! Generic project names will be harder to search for. - - - - - - - Summary* - - Give a short description of your project that will appear on search - pages. - - - - - - - Categories - - Select up to 3 categories that will help others - find your project. - - - - - - - Additional Categories - - Select more categories that will help others - find your project. These are searchable, but not - displayed in search. - - - - - - - URL* - - - - https://modrinth.com/{{ project.project_type.toLowerCase() }}/ - - - - - - - - Icon - - - - - - - Revert - - - - - - Supported environments - - Let others know what environments your project supports. - - - - Client* - - - - Server* - - - - - - - - Description* - - - - You can type an extended description of your mod here. This editor - supports - Markdown. HTML can also be used inside your description, not including styles, - scripts, and iframes (though YouTube iframes are allowed). - - - - - - - - - - External links - - - Issue tracker - - - - Source code - - - - Wiki page - - - - Discord invite - - - - - License* - - - - It is very important to choose a proper license for your mod. You - may choose one from our list or provide a custom license. You may - also provide a custom URL to your chosen license; otherwise, the - license text will be displayed. - - Enter a valid - SPDX license identifier - in the marked area. If your license does not have a SPDX - identifier (for example, if you created the license yourself or if - the license is Minecraft-specific), simply check the box and enter - the name of the license instead. - - - Confused? See our - - licensing guide - for more information. - - - - - - - Allow later editions of this license - - - License does not have a SPDX identifier - - - - - - - - - Donation links - - - - Add a link - - - - - - Donation Link - - - - Donation Platform - - - - - Remove link - - - - - - - - - - diff --git a/pages/_type/_id/settings/description.vue b/pages/_type/_id/settings/description.vue new file mode 100644 index 000000000..787a80c73 --- /dev/null +++ b/pages/_type/_id/settings/description.vue @@ -0,0 +1,144 @@ + + + + + Description + + You can type an extended description of your mod here. This editor + supports + Markdown. HTML can also be used inside your description, not including + styles, scripts, and iframes (though YouTube iframes are allowed). + + The description must clearly and honestly describe the purpose and + function of the project. See section 2.1 of the + Content Rules + for the full requirements. + + + + + + + + + + + + Save changes + + + + + + + + diff --git a/pages/_type/_id/settings/index.vue b/pages/_type/_id/settings/index.vue new file mode 100644 index 000000000..aa1d2d574 --- /dev/null +++ b/pages/_type/_id/settings/index.vue @@ -0,0 +1,419 @@ + + + + + + + Project information + + + + Icon + + + + + + + + + + Remove icon + + + + + + Name + + + + + URL + + + https://modrinth.com/mod/ + + + + + Summary + + + + + + + + Client-side + + Select based on if the + {{ $formatProjectType(project.project_type).toLowerCase() }} has + functionality on the client side. Just because a mod works in + Singleplayer doesn't mean it has actual client-side functionality. + + + + + + + Server-side + + Select based on if the + {{ $formatProjectType(project.project_type).toLowerCase() }} has + functionality on the logical server. Remember + that Singleplayer contains an integrated server. + + + + + + + + Visibility + + Set the visibility of your project. Listed and archived projects are + visible in search. Unlisted projects are published, but not visible + in search or on user profiles. Private projects are only accessible + by members of the project. + + + + + + + + Save changes + + + + + + + + Delete project + + + + Removes your project from Modrinth's servers and search. Clicking on + this will delete your project, so be extra careful! + + + + Delete project + + + + + + + diff --git a/pages/_type/_id/settings/license.vue b/pages/_type/_id/settings/license.vue new file mode 100644 index 000000000..d46fd7dbb --- /dev/null +++ b/pages/_type/_id/settings/license.vue @@ -0,0 +1,286 @@ + + + + + + License + + It is very important to choose a proper license for your + {{ $formatProjectType(project.project_type).toLowerCase() }}. You + may choose one from our list or provide a custom license. You may + also provide a custom URL to your chosen license; otherwise, the + license text will be displayed. + + Enter a valid + + SPDX license identifier + in the marked area. If your license does not have a SPDX + identifier (for example, if you created the license yourself or if + the license is Minecraft-specific), simply check the box and enter + the name of the license instead. + + + Confused? See our + + licensing guide + for more information. + + + + + + + Allow later editions of this license + + + License does not have a SPDX identifier + + + + + + + + + Save changes + + + + + + + + diff --git a/pages/_type/_id/settings/links.vue b/pages/_type/_id/settings/links.vue new file mode 100644 index 000000000..3811ff2e1 --- /dev/null +++ b/pages/_type/_id/settings/links.vue @@ -0,0 +1,286 @@ + + + + External links + + + Issue tracker + + A place for users to report bugs, issues, and concerns about your + project. + + + + + + + Source code + + A page/repository containing the source code for your project + + + + + + + Wiki page + + A page containing information, documentation, and help for the + project. + + + + + + + Discord invite + + An invitation link to your Discord server. + + + + + + Donation links + + Add donation links for users to support you directly. + + + + + + + + + + + Save changes + + + + + + + + diff --git a/pages/_type/_id/settings.vue b/pages/_type/_id/settings/members.vue similarity index 78% rename from pages/_type/_id/settings.vue rename to pages/_type/_id/settings/members.vue index 628290e17..e005f6be1 100644 --- a/pages/_type/_id/settings.vue +++ b/pages/_type/_id/settings/members.vue @@ -1,77 +1,35 @@ - - General settings - - - Edit project information - - Edit your project's name, description, categories, and more. - - - Edit + + + Manage members + - - - Delete project - - Removes your project from Modrinth's servers and search. Clicking on - this will delete your project, so be extra careful! - + + Invite a member + + Enter the Modrinth username of the person you'd like to invite to be a + member of this project. - - Delete project + + + + Username + + + Invite - - Manage members - - - Invite a member - - Enter the Modrinth username of the person you'd like to invite to be - a member of this project. - - - - - Username - - - Invite - - - - - - + + - + + + + Save changes + - + Remove member - + Transfer ownership - - - Save changes - @@ -291,30 +249,26 @@ + diff --git a/pages/_type/_id/versions.vue b/pages/_type/_id/versions.vue index f8ac1b618..8531a501d 100644 --- a/pages/_type/_id/versions.vue +++ b/pages/_type/_id/versions.vue @@ -32,7 +32,7 @@ - - - + + + @@ -36,7 +36,7 @@ import NavStackItem from '~/components/ui/NavStackItem' import DashboardIcon from '~/assets/images/utils/dashboard.svg?inline' // import ChartIcon from '~/assets/images/utils/chart.svg?inline' import CurrencyIcon from '~/assets/images/utils/currency.svg?inline' -// import ListIcon from '~/assets/images/utils/list.svg?inline' +import ListIcon from '~/assets/images/utils/list.svg?inline' const monetization = true @@ -48,7 +48,7 @@ export default { DashboardIcon, // ChartIcon, CurrencyIcon, - // ListIcon, + ListIcon, }, methods: { hasMonetization() { diff --git a/pages/dashboard/analytics.vue b/pages/dashboard/analytics.vue index 595be8c51..c544f3e7e 100644 --- a/pages/dashboard/analytics.vue +++ b/pages/dashboard/analytics.vue @@ -2,6 +2,10 @@ Analytics + You found a secret! + Click here for fancy graphs! diff --git a/pages/dashboard/index.vue b/pages/dashboard/index.vue index 41565b551..50f489575 100644 --- a/pages/dashboard/index.vue +++ b/pages/dashboard/index.vue @@ -2,8 +2,8 @@ Overview - - + + Total downloads {{ @@ -24,7 +24,7 @@ - + Total followers {{ @@ -47,7 +47,7 @@ - + Total revenue {{ $formatMoney(payouts.all_time) }} {{ $formatMoney(payouts.last_month) }} this month @@ -58,7 +58,7 @@ - + Current balance {{ $formatMoney($auth.user.payout_data.balance) }} @@ -130,33 +130,4 @@ export default { methods: {}, } - + diff --git a/pages/dashboard/projects.vue b/pages/dashboard/projects.vue index 14a2bcfad..85c430760 100644 --- a/pages/dashboard/projects.vue +++ b/pages/dashboard/projects.vue @@ -1,22 +1,664 @@ + + + + Any links you specify below will be overwritten on each of the + selected projects. Any you leave blank will be ignored. You can clear + a link from all selected projects using the trash can button. + + + + Issue tracker + + + + + + + + + Source code + + + + + + + + + Wiki page + + + + + + + + + Discord invite + + + + + + + + + + Changes will be applied to + {{ selectedProjects.length }} project{{ + selectedProjects.length > 1 ? 's' : '' + }}. + + + + {{ project.title }} + + + and {{ selectedProjects.length - 3 }} more... + + + + + + + Cancel + + + + Save changes + + + + + - Projects + + Projects + + + + Create a project + + + + + You don't have any projects yet. Click the green button above to begin. + + + You can edit multiple projects at once by selecting them below. + + + + Edit links + + + + Sort By + + + + + + + + + + Icon + Name + ID + Type + Status + + + + + it !== project + )) + : selectedProjects.push(project) + " + /> + + + + + + + + + + + + + {{ project.title }} + + + + + + + + + + {{ $formatProjectType(project.project_type) }} + + + + + + + + + + + + + + - + diff --git a/pages/dashboard/revenue.vue b/pages/dashboard/revenue.vue index a7b7102a7..980d1af41 100644 --- a/pages/dashboard/revenue.vue +++ b/pages/dashboard/revenue.vue @@ -22,7 +22,7 @@ > - + diff --git a/pages/frog.vue b/pages/frog.vue index a3cae8a35..5f59f4f09 100644 --- a/pages/frog.vue +++ b/pages/frog.vue @@ -1,13 +1,11 @@ - - - Frog - You've been frogged! πΈ - - + + Frog + You've been frogged! πΈ + @@ -19,11 +17,17 @@ export default { diff --git a/pages/moderation.vue b/pages/moderation.vue index 4ee748b0d..5363679fb 100644 --- a/pages/moderation.vue +++ b/pages/moderation.vue @@ -91,17 +91,24 @@ > Approve - Unlist + Withhold - - Manage - - + Manage + - Followed projects - - + - Clear all - - + + diff --git a/pages/search.vue b/pages/search.vue index 9eacb15d2..268cb1e10 100644 --- a/pages/search.vue +++ b/pages/search.vue @@ -46,26 +46,9 @@ { - obj[key] = categories[key] - return obj - }, {}) - - for (const header of Object.keys(categories)) { - newVals[header].sort((a, b) => a.name.localeCompare(b.name)) - } + const newVals = Object.keys(categories).reduce((obj, key) => { + obj[key] = categories[key] + return obj + }, {}) return newVals }, diff --git a/pages/settings.vue b/pages/settings.vue index d3a72258d..12084901d 100644 --- a/pages/settings.vue +++ b/pages/settings.vue @@ -15,11 +15,7 @@ - + diff --git a/pages/settings/index.vue b/pages/settings/index.vue index 4db45052c..a0b40b6db 100644 --- a/pages/settings/index.vue +++ b/pages/settings/index.vue @@ -64,7 +64,7 @@ {{ projectType.name }} display mode diff --git a/pages/settings/monetization.vue b/pages/settings/monetization.vue index f2ae9b7dd..6711060d9 100644 --- a/pages/settings/monetization.vue +++ b/pages/settings/monetization.vue @@ -25,7 +25,7 @@ Program. Setup a method of receiving payments below to enable monetization. - + - +
+ {{ project.description }} +
- {{ project.description }} -
- Your project is currently not viewable by people who are not part - of your team. If you would like to publish your project, click the - button below to send your project in for review. -
+ Removes your project from Modrinth's servers and search. Clicking on + this will delete your project, so be extra careful! +
You found a secret!
+ Any links you specify below will be overwritten on each of the + selected projects. Any you leave blank will be ignored. You can clear + a link from all selected projects using the trash can button. +
+ Changes will be applied to + {{ selectedProjects.length }} project{{ + selectedProjects.length > 1 ? 's' : '' + }}. +
+ You don't have any projects yet. Click the green button above to begin. +
You can edit multiple projects at once by selecting them below.
You've been frogged! πΈ