mirror of
https://github.com/HangarMC/Hangar.git
synced 2025-01-30 14:30:08 +08:00
initial design work for the project docs pages
Signed-off-by: MiniDigger <admin@benndorf.dev>
This commit is contained in:
parent
fa95259216
commit
ce3ca1bd45
@ -1,6 +1,7 @@
|
||||
@import '~vuetify/src/styles/styles.sass';
|
||||
@import 'utils';
|
||||
@import "markdown";
|
||||
@import "theme/base";
|
||||
|
||||
.text-transform-unset {
|
||||
text-transform: unset;
|
||||
|
16
frontend/assets/theme/base.scss
Normal file
16
frontend/assets/theme/base.scss
Normal file
@ -0,0 +1,16 @@
|
||||
@import '~vuetify/src/styles/styles.sass';
|
||||
|
||||
.v-divider {
|
||||
border: 1px solid rgba(255, 255, 255, 0.15) !important;
|
||||
}
|
||||
|
||||
.v-card,
|
||||
.v-sheet.v-list {
|
||||
background-color: #272727 !important;
|
||||
}
|
||||
.v-btn.v-btn--has-bg {
|
||||
background-color: #1E1E1E !important;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
@ -4,3 +4,11 @@
|
||||
// $font-size-root: 20px;
|
||||
// !!!!---No imports in this file---!!!!
|
||||
//@import '~vue-cli-plugin-vuetify-preset-reply/preset/variables.scss';
|
||||
|
||||
@import '~vuetify/src/styles/styles.sass';
|
||||
|
||||
$container-max-widths: (
|
||||
'md': 1000px,
|
||||
'lg': 1500px,
|
||||
'xl': 1680px
|
||||
)
|
||||
|
@ -19,8 +19,10 @@ export default class Announcement extends Vue {
|
||||
<style lang="scss" scoped>
|
||||
.v-alert {
|
||||
text-align: center;
|
||||
margin-bottom: 1rem;
|
||||
flex: 0 0 100%;
|
||||
max-width: 100%;
|
||||
min-height: 43px;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
</style>
|
||||
|
@ -101,4 +101,8 @@ img {
|
||||
a {
|
||||
margin: 0 3px;
|
||||
}
|
||||
|
||||
footer {
|
||||
margin-top: 12px;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<v-app-bar fixed app>
|
||||
<v-app-bar height="100px">
|
||||
<v-menu bottom offset-y open-on-hover transition="slide-y-transition" close-delay="100">
|
||||
<template #activator="{ on, attrs }">
|
||||
<v-btn text x-large class="align-self-center px-1" v-bind="attrs" :ripple="false" v-on="on">
|
||||
<NuxtLink class="float-left" to="/" exact>
|
||||
<v-img height="55" width="220" src="https://papermc.io/images/logo-marker.svg" alt="Paper logo" />
|
||||
<v-img height="60" width="220" src="https://papermc.io/images/logo-marker.svg" alt="Paper logo" />
|
||||
</NuxtLink>
|
||||
|
||||
<v-icon>mdi-chevron-down</v-icon>
|
||||
@ -244,9 +244,7 @@ export default class Header extends HangarComponent {
|
||||
.v-badge--bordered.header-badge .v-badge__badge::after {
|
||||
border-color: #272727 !important;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.avatar-button {
|
||||
//border: 2px white solid;
|
||||
.v-image {
|
||||
margin: 20px;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-sheet :color="color" class="darken-1" rounded elevation="2">
|
||||
<v-sheet :color="color" rounded elevation="2">
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<div v-if="!$fetchState.pending" class="page-rendered" :class="innerClass" v-html="renderedMarkdown" />
|
||||
<v-row v-else no-gutters justify="center">
|
||||
|
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div class="markdown-editor">
|
||||
<div v-show="isEditing && !preview" class="ml-4">
|
||||
<div v-show="isEditing && !preview">
|
||||
<!-- TODO validations for pageContent min/max length from validations state -->
|
||||
<v-textarea v-model="rawEdited" outlined :rows="rawEdited.split(/\r\n|\r|\n/g).length + 3" :rules="rules" />
|
||||
</div>
|
||||
<Markdown v-show="!isEditing" :raw="raw" class="ml-4" />
|
||||
<Markdown v-if="preview" :raw="rawEdited" class="ml-4" inner-class="pl-5" />
|
||||
<Markdown v-show="!isEditing" :raw="raw" />
|
||||
<Markdown v-if="preview" :raw="rawEdited" inner-class="pl-5" />
|
||||
<v-btn v-show="!isEditing" class="page-btn edit-btn info" fab absolute icon x-small @click="isEditing = true">
|
||||
<v-icon>mdi-pencil</v-icon>
|
||||
</v-btn>
|
||||
@ -38,7 +38,7 @@
|
||||
|
||||
<v-btn
|
||||
v-show="isEditing && cancellable"
|
||||
class="page-btn cancel-btn warning red darken-2"
|
||||
class="page-btn cancel-btn warning red darken-1"
|
||||
fab
|
||||
absolute
|
||||
icon
|
||||
@ -118,23 +118,23 @@ export default class MarkdownEditor extends Vue {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-btn {
|
||||
left: 0;
|
||||
left: -20px;
|
||||
|
||||
&.edit-btn,
|
||||
&.save-btn {
|
||||
top: -16px;
|
||||
top: 5px;
|
||||
}
|
||||
|
||||
&.preview-btn {
|
||||
top: 22px;
|
||||
top: 45px;
|
||||
}
|
||||
|
||||
&.delete-btn {
|
||||
top: 62px;
|
||||
top: 78px;
|
||||
}
|
||||
|
||||
&.cancel-btn {
|
||||
top: 102px;
|
||||
top: 118px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,9 +3,9 @@
|
||||
<template #activator="{ on: dialogOn, attrs }">
|
||||
<v-tooltip :disabled="!project.userActions.flagged" bottom>
|
||||
<template #activator="{ on: tooltipOn }">
|
||||
<div v-on="tooltipOn">
|
||||
<div class="flag-modal-trigger" v-on="tooltipOn">
|
||||
<!-- wrap in div so tooltip shows up when the button is disabled -->
|
||||
<v-btn v-bind="attrs" color="warning" :disabled="project.userActions.flagged" :class="activatorClass" v-on="dialogOn">
|
||||
<v-btn v-bind="attrs" small color="warning" :disabled="project.userActions.flagged" :class="activatorClass" v-on="dialogOn">
|
||||
<v-icon>mdi-flag</v-icon>
|
||||
{{ $t('project.actions.flag') }}
|
||||
</v-btn>
|
||||
|
@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="button-group d-inline-block">
|
||||
<div class="button-group">
|
||||
<v-menu v-if="platformSelection" offset-y>
|
||||
<template #activator="{ on, attrs }">
|
||||
<v-btn style="min-width: 32px" class="px-2" color="primary darken-1" dark v-bind="attrs" elevation="0" v-on="on">
|
||||
<v-btn style="min-width: 32px" class="px-2" color="primary darken-1" height="52px" dark v-bind="attrs" elevation="0" v-on="on">
|
||||
<v-icon v-text="`$vuetify.icons.${selectedPlatform.toLowerCase()}`" />
|
||||
</v-btn>
|
||||
</template>
|
||||
@ -18,7 +18,7 @@
|
||||
</v-list-item>
|
||||
</v-list-item-group>
|
||||
</v-list> </v-menu
|
||||
><v-btn color="primary" :small="small" :loading="loading" elevation="0" @click="checkAndDownload">
|
||||
><v-btn color="primary" :small="small" :loading="loading" elevation="0" height="52px" @click="checkAndDownload">
|
||||
<v-icon>mdi-download-outline</v-icon>
|
||||
{{ external ? $t('version.page.downloadExternal') : $t('version.page.download') }} </v-btn
|
||||
><HangarModal
|
||||
@ -38,7 +38,16 @@
|
||||
<em>{{ $t('version.page.confirmation.disclaimer') }}</em> </HangarModal
|
||||
><v-tooltip v-if="copyButton" v-model="copySuccessful" bottom>
|
||||
<template #activator="{ attrs }">
|
||||
<v-btn style="min-width: 32px" class="px-2" color="primary lighten-1" :small="small" v-bind="attrs" elevation="0" @click="copyDownloadUrl">
|
||||
<v-btn
|
||||
style="min-width: 32px"
|
||||
class="px-2"
|
||||
color="primary lighten-1"
|
||||
height="52px"
|
||||
:small="small"
|
||||
v-bind="attrs"
|
||||
elevation="0"
|
||||
@click="copyDownloadUrl"
|
||||
>
|
||||
<v-icon>mdi-content-copy</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
|
117
frontend/components/projects/ProjectTabs.vue
Normal file
117
frontend/components/projects/ProjectTabs.vue
Normal file
@ -0,0 +1,117 @@
|
||||
<template>
|
||||
<v-tabs>
|
||||
<v-tab v-for="tab in tabs" :key="tab.title" :exact="!!tab.exact" :to="tab.external ? '/linkout?remoteUrl=' + tab.link : tab.link" nuxt>
|
||||
<v-icon left>
|
||||
{{ tab.icon }}
|
||||
</v-icon>
|
||||
{{ tab.title }}
|
||||
<v-icon v-if="tab.external" small class="mb-1 ml-1" color="primary"> mdi-open-in-new</v-icon>
|
||||
</v-tab>
|
||||
</v-tabs>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component } from 'nuxt-property-decorator';
|
||||
import { TranslateResult } from 'vue-i18n';
|
||||
import { HangarProjectMixin } from '~/components/mixins';
|
||||
import VisibilityChangerModal from '~/components/modals/VisibilityChangerModal.vue';
|
||||
import Markdown from '~/components/markdown/Markdown.vue';
|
||||
|
||||
interface Tab {
|
||||
title: string | TranslateResult;
|
||||
icon: string;
|
||||
link: string;
|
||||
external: boolean;
|
||||
exact?: boolean;
|
||||
}
|
||||
|
||||
@Component({
|
||||
components: { Markdown, VisibilityChangerModal },
|
||||
})
|
||||
export default class ProjectTabs extends HangarProjectMixin {
|
||||
get tabs(): Tab[] {
|
||||
const tabs = [] as Tab[];
|
||||
tabs.push({ title: this.$t('project.tabs.docs'), icon: 'mdi-book', link: this.slug, external: false, exact: true });
|
||||
tabs.push({
|
||||
title: this.$t('project.tabs.versions'),
|
||||
icon: 'mdi-download',
|
||||
link: this.slug + '/versions',
|
||||
external: false,
|
||||
});
|
||||
if ((this.project.settings.forumSync && this.project.postId) || this.$perms.canEditSubjectSettings) {
|
||||
tabs.push({
|
||||
title: this.$t('project.tabs.discuss'),
|
||||
icon: 'mdi-account-group',
|
||||
link: this.slug + '/discuss',
|
||||
external: false,
|
||||
});
|
||||
}
|
||||
if (this.$perms.canEditSubjectSettings) {
|
||||
tabs.push({
|
||||
title: this.$t('project.tabs.settings'),
|
||||
icon: 'mdi-cog',
|
||||
link: this.slug + '/settings',
|
||||
external: false,
|
||||
});
|
||||
}
|
||||
|
||||
if (this.project.settings.homepage) {
|
||||
tabs.push({
|
||||
title: this.$t('project.tabs.homepage'),
|
||||
icon: 'mdi-home',
|
||||
link: this.project.settings.homepage,
|
||||
external: true,
|
||||
});
|
||||
}
|
||||
if (this.project.settings.issues) {
|
||||
tabs.push({
|
||||
title: this.$t('project.tabs.issues'),
|
||||
icon: 'mdi-bug',
|
||||
link: this.project.settings.issues,
|
||||
external: true,
|
||||
});
|
||||
}
|
||||
if (this.project.settings.source) {
|
||||
tabs.push({
|
||||
title: this.$t('project.tabs.source'),
|
||||
icon: 'mdi-code-tags',
|
||||
link: this.project.settings.source,
|
||||
external: true,
|
||||
});
|
||||
}
|
||||
if (this.project.settings.support) {
|
||||
tabs.push({
|
||||
title: this.$t('project.tabs.support'),
|
||||
icon: 'mdi-chat-question',
|
||||
link: this.project.settings.support,
|
||||
external: true,
|
||||
});
|
||||
}
|
||||
return tabs;
|
||||
}
|
||||
|
||||
get slug(): string {
|
||||
return `/${this.project.namespace.owner}/${this.project.namespace.slug}`;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.v-tabs {
|
||||
margin-top: 12px;
|
||||
}
|
||||
.v-tabs-bar {
|
||||
background-color: #272727 !important;
|
||||
|
||||
a:not(.v-tab--active) {
|
||||
& .v-icon--left {
|
||||
color: white !important;
|
||||
}
|
||||
color: white !important;
|
||||
}
|
||||
}
|
||||
.v-slide-group__prev--disabled,
|
||||
.v-slide-group__next--disabled {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="user-avatar-wrap">
|
||||
<NuxtLink :to="url">
|
||||
<img :title="username" :src="src" :alt="username" :class="'user-avatar ' + clazz" @error="errored = true" />
|
||||
</NuxtLink>
|
||||
|
@ -1,12 +1,13 @@
|
||||
<template>
|
||||
<v-app>
|
||||
<Header />
|
||||
<v-main>
|
||||
<v-container>
|
||||
<div class="announcements">
|
||||
<template v-if="announcements">
|
||||
<Announcement v-for="(announcement, idx) in announcements" :key="idx" :announcement="announcement" />
|
||||
</template>
|
||||
|
||||
</div>
|
||||
<Header />
|
||||
<v-main>
|
||||
<v-container id="main" fluid>
|
||||
<DonationResult />
|
||||
<nuxt />
|
||||
</v-container>
|
||||
@ -42,3 +43,12 @@ export default class DefaultLayout extends Vue {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
#main {
|
||||
padding: 0;
|
||||
}
|
||||
.v-main {
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
</style>
|
||||
|
@ -90,7 +90,7 @@ const msgs: LocaleMessageObject = {
|
||||
noWatchers: 'There are no watchers on this project yet 😢',
|
||||
members: 'Members',
|
||||
category: {
|
||||
info: 'Category: {0}',
|
||||
info: 'Category',
|
||||
admin_tools: 'Admin Tools',
|
||||
chat: 'Chat',
|
||||
dev_tools: 'Developer Tools',
|
||||
@ -212,11 +212,11 @@ const msgs: LocaleMessageObject = {
|
||||
sendForApproval: 'Send for approval',
|
||||
info: {
|
||||
title: 'Information',
|
||||
publishDate: 'Published on {0}',
|
||||
views: '0 views | {0} view | {0} views',
|
||||
totalDownloads: '0 total downloads | {0} total download | {0} total downloads',
|
||||
stars: '0 stars | {0} star | {0} stars',
|
||||
watchers: '0 watchers | {0} watcher | {0} watchers'
|
||||
publishDate: 'Published on',
|
||||
views: 'Views | View | Views',
|
||||
totalDownloads: 'Total downloads | Total download | Total downloads',
|
||||
stars: 'Stars | Star | Stars',
|
||||
watchers: 'Watchers | Watcher | Watchers'
|
||||
},
|
||||
promotedVersions: 'Promoted Versions',
|
||||
license: {
|
||||
|
@ -10,7 +10,11 @@
|
||||
"lint": "eslint --ext \".js,.vue,.ts\" .",
|
||||
"prepare": "cd .. && husky install frontend/.husky"
|
||||
},
|
||||
"eslintIgnore": [".gitignore", "locales/*", "sw.js"],
|
||||
"eslintIgnore": [
|
||||
".gitignore",
|
||||
"locales/*",
|
||||
"sw.js"
|
||||
],
|
||||
"lint-staged": {
|
||||
"*.{ts,js,vue}": "eslint"
|
||||
},
|
||||
@ -28,6 +32,8 @@
|
||||
"filesize": "6.3.0",
|
||||
"jwt-decode": "3.1.2",
|
||||
"lodash-es": "4.17.21",
|
||||
"lru-cache": "6.0.0",
|
||||
"minify-css-string": "1.0.0",
|
||||
"nuxt": "2.15.7",
|
||||
"nuxt-i18n": "Machine-Maker/i18n-module#fix/mixing-mem-leak",
|
||||
"nuxt-property-decorator": "2.9.1",
|
||||
@ -47,6 +53,7 @@
|
||||
"@types/chartist": "0.11.0",
|
||||
"@types/diff-match-patch": "1.0.32",
|
||||
"@types/lodash-es": "4.17.4",
|
||||
"@types/lru-cache": "5.1.1",
|
||||
"@types/swagger-ui-dist": "3.30.0",
|
||||
"eslint": "7.29.0",
|
||||
"eslint-config-prettier": "8.3.0",
|
||||
|
@ -22,8 +22,10 @@
|
||||
<Markdown v-if="project.lastVisibilityChangeComment" :raw="project.lastVisibilityChangeComment" />
|
||||
</v-alert>
|
||||
</template>
|
||||
<div class="project-header">
|
||||
<v-container>
|
||||
<v-row>
|
||||
<v-col cols="1">
|
||||
<v-col cols="auto" align-self="center">
|
||||
<UserAvatar
|
||||
:username="project.name"
|
||||
:href="'/' + project.namespace.owner + '/' + project.namespace.slug"
|
||||
@ -31,7 +33,7 @@
|
||||
clazz="user-avatar-md"
|
||||
></UserAvatar>
|
||||
</v-col>
|
||||
<v-col cols="auto">
|
||||
<v-col cols="auto" align-self="center">
|
||||
<h1 class="d-inline">
|
||||
<NuxtLink :to="'/' + project.namespace.owner">
|
||||
{{ project.namespace.owner }}
|
||||
@ -41,84 +43,28 @@
|
||||
{{ project.name }}
|
||||
</NuxtLink>
|
||||
</h1>
|
||||
<div>
|
||||
<v-subheader>{{ project.description }}</v-subheader>
|
||||
</div>
|
||||
</v-col>
|
||||
<v-spacer />
|
||||
<v-col v-if="isLoggedIn" cols="3">
|
||||
<v-row no-gutters justify="end">
|
||||
<v-tooltip v-if="!$util.isCurrentUser(project.owner.id)" bottom>
|
||||
<template #activator="{ on }">
|
||||
<v-btn icon @click="toggleStar" v-on="on">
|
||||
<v-icon v-if="project.userActions.starred" color="amber"> mdi-star </v-icon>
|
||||
<v-icon v-else color="amber"> mdi-star-outline </v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<span v-if="project.userActions.starred">{{ $t('project.actions.unstar') }}</span>
|
||||
<span v-else>{{ $t('project.actions.star') }}</span>
|
||||
</v-tooltip>
|
||||
|
||||
<v-tooltip v-if="!$util.isCurrentUser(project.owner.id)" bottom>
|
||||
<template #activator="{ on }">
|
||||
<v-btn icon @click="toggleWatch" v-on="on">
|
||||
<v-icon v-if="project.userActions.watching"> mdi-eye-off </v-icon>
|
||||
<v-icon v-else> mdi-eye </v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<span v-if="project.userActions.watching">{{ $t('project.actions.unwatch') }}</span>
|
||||
<span v-else>{{ $t('project.actions.watch') }}</span>
|
||||
</v-tooltip>
|
||||
<FlagModal v-if="isLoggedIn && !$util.isCurrentUser(project.owner.id)" :project="project" activator-class="ml-1" />
|
||||
<v-menu v-if="$perms.isStaff" bottom offset-y open-on-hover>
|
||||
<template #activator="{ on, attrs }">
|
||||
<v-btn v-bind="attrs" class="ml-1" color="info" v-on="on">
|
||||
{{ $t('project.actions.adminActions') }}
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-item :to="slug + '/flags'" nuxt>
|
||||
<v-list-item-title>
|
||||
{{ $t('project.actions.flagHistory', [project.info.flagCount]) }}
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item :to="slug + '/notes'" nuxt>
|
||||
<v-list-item-title>
|
||||
{{ $t('project.actions.staffNotes', [project.info.noteCount]) }}
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item :to="'/admin/log/?projectFilter=' + slug" nuxt>
|
||||
<v-list-item-title>
|
||||
{{ $t('project.actions.userActionLogs') }}
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item :href="$util.forumUrl(project.namespace.owner)">
|
||||
<v-list-item-title>
|
||||
{{ $t('project.actions.forum') }}
|
||||
<v-icon>mdi-open-in-new</v-icon>
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</v-row>
|
||||
<v-col cols="auto" align-self="center">
|
||||
<DownloadButton
|
||||
v-if="project.recommendedVersions && Object.keys(project.recommendedVersions).length > 0"
|
||||
:project="project"
|
||||
:platform-selection="true"
|
||||
:small="false"
|
||||
/>
|
||||
</v-col>
|
||||
<ProjectTabs :project="project"></ProjectTabs>
|
||||
</v-row>
|
||||
<v-row>
|
||||
<v-tabs>
|
||||
<v-tab v-for="tab in tabs" :key="tab.title" :exact="!!tab.exact" :to="tab.external ? '/linkout?remoteUrl=' + tab.link : tab.link" nuxt>
|
||||
<v-icon left>
|
||||
{{ tab.icon }}
|
||||
</v-icon>
|
||||
{{ tab.title }}
|
||||
<v-icon v-if="tab.external" small class="mb-1 ml-1" color="primary"> mdi-open-in-new </v-icon>
|
||||
</v-tab>
|
||||
</v-tabs>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</div>
|
||||
<v-container>
|
||||
<NuxtChild class="mt-5" :project="project">
|
||||
<v-tab-item>
|
||||
{{ $route.name }}
|
||||
</v-tab-item>
|
||||
</NuxtChild>
|
||||
</v-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -127,24 +73,17 @@ import { Component } from 'nuxt-property-decorator';
|
||||
import { Context } from '@nuxt/types';
|
||||
import { HangarProject } from 'hangar-internal';
|
||||
import { NavigationGuardNext, Route } from 'vue-router';
|
||||
import { TranslateResult } from 'vue-i18n';
|
||||
import { Markdown } from '~/components/markdown';
|
||||
import FlagModal from '~/components/modals/projects/FlagModal.vue';
|
||||
import { UserAvatar } from '~/components/users';
|
||||
import { Visibility } from '~/types/enums';
|
||||
import { HangarComponent } from '~/components/mixins';
|
||||
|
||||
interface Tab {
|
||||
title: string | TranslateResult;
|
||||
icon: string;
|
||||
link: string;
|
||||
external: boolean;
|
||||
exact?: boolean;
|
||||
}
|
||||
import ProjectTabs from '~/components/projects/ProjectTabs.vue';
|
||||
import DownloadButton from '~/components/projects/DownloadButton.vue';
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
FlagModal,
|
||||
DownloadButton,
|
||||
ProjectTabs,
|
||||
Markdown,
|
||||
UserAvatar,
|
||||
},
|
||||
@ -171,32 +110,6 @@ export default class ProjectPage extends HangarComponent {
|
||||
return { project };
|
||||
}
|
||||
|
||||
get tabs(): Tab[] {
|
||||
const tabs = [] as Tab[];
|
||||
tabs.push({ title: this.$t('project.tabs.docs'), icon: 'mdi-book', link: this.slug, external: false, exact: true });
|
||||
tabs.push({ title: this.$t('project.tabs.versions'), icon: 'mdi-download', link: this.slug + '/versions', external: false });
|
||||
if ((this.project.settings.forumSync && this.project.postId) || this.$perms.canEditSubjectSettings) {
|
||||
tabs.push({ title: this.$t('project.tabs.discuss'), icon: 'mdi-account-group', link: this.slug + '/discuss', external: false });
|
||||
}
|
||||
if (this.$perms.canEditSubjectSettings) {
|
||||
tabs.push({ title: this.$t('project.tabs.settings'), icon: 'mdi-cog', link: this.slug + '/settings', external: false });
|
||||
}
|
||||
|
||||
if (this.project.settings.homepage) {
|
||||
tabs.push({ title: this.$t('project.tabs.homepage'), icon: 'mdi-home', link: this.project.settings.homepage, external: true });
|
||||
}
|
||||
if (this.project.settings.issues) {
|
||||
tabs.push({ title: this.$t('project.tabs.issues'), icon: 'mdi-bug', link: this.project.settings.issues, external: true });
|
||||
}
|
||||
if (this.project.settings.source) {
|
||||
tabs.push({ title: this.$t('project.tabs.source'), icon: 'mdi-code-tags', link: this.project.settings.source, external: true });
|
||||
}
|
||||
if (this.project.settings.support) {
|
||||
tabs.push({ title: this.$t('project.tabs.support'), icon: 'mdi-chat-question', link: this.project.settings.support, external: true });
|
||||
}
|
||||
return tabs;
|
||||
}
|
||||
|
||||
get isPublic(): Boolean {
|
||||
return this.project.visibility === Visibility.PUBLIC;
|
||||
}
|
||||
@ -213,24 +126,6 @@ export default class ProjectPage extends HangarComponent {
|
||||
return `/${this.project.namespace.owner}/${this.project.namespace.slug}`;
|
||||
}
|
||||
|
||||
toggleStar() {
|
||||
this.$api
|
||||
.requestInternal<void>(`projects/project/${this.project.id}/star/${!this.project.userActions.starred}`, true, 'post')
|
||||
.then(() => {
|
||||
this.project.userActions.starred = !this.project.userActions.starred;
|
||||
})
|
||||
.catch((err) => this.$util.handleRequestError(err, 'project.error.star'));
|
||||
}
|
||||
|
||||
toggleWatch() {
|
||||
this.$api
|
||||
.requestInternal(`projects/project/${this.project.id}/watch/${!this.project.userActions.watching}`, true, 'post')
|
||||
.then(() => {
|
||||
this.project.userActions.watching = !this.project.userActions.watching;
|
||||
})
|
||||
.catch((err) => this.$util.handleRequestError(err, 'project.error.watch'));
|
||||
}
|
||||
|
||||
sendForApproval() {
|
||||
this.loading.approval = true;
|
||||
this.$api
|
||||
@ -254,3 +149,39 @@ export default class ProjectPage extends HangarComponent {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
div.project-header {
|
||||
background-color: #1d1d1d;
|
||||
min-height: 125px;
|
||||
|
||||
.container {
|
||||
padding: 15px 0 0 0;
|
||||
.row {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.col:first-child {
|
||||
margin-left: 50px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.user-avatar-wrap,
|
||||
.user-avatar {
|
||||
height: 95px;
|
||||
width: 95px;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.v-subheader {
|
||||
padding: 0;
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<v-row>
|
||||
<v-col v-if="page.contents" cols="12" md="8">
|
||||
<v-col v-if="page.contents" cols="12" md="8" class="main-page-content">
|
||||
<v-divider />
|
||||
<MarkdownEditor
|
||||
v-if="$perms.canEditPage"
|
||||
ref="editor"
|
||||
@ -18,17 +19,48 @@
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<v-card>
|
||||
<v-card-title v-text="$t('project.info.title')" />
|
||||
<v-card-text>
|
||||
<DownloadButton
|
||||
v-if="project.recommendedVersions && Object.keys(project.recommendedVersions).length > 0"
|
||||
:project="project"
|
||||
:platform-selection="true"
|
||||
:small="false"
|
||||
/>
|
||||
|
||||
<div v-if="project.settings.donation.enable" style="margin-top: 5px">
|
||||
<v-card-title>
|
||||
<v-col cols="auto">
|
||||
{{ $t('project.info.title') }}
|
||||
</v-col>
|
||||
<v-col v-if="isLoggedIn && !$util.isCurrentUser(project.owner.id)" cols="auto">
|
||||
<FlagModal :project="project" activator-class="ml-1" />
|
||||
</v-col>
|
||||
<v-col v-if="$perms.isStaff" cols="auto">
|
||||
<v-menu bottom offset-y open-on-hover>
|
||||
<template #activator="{ on, attrs }">
|
||||
<v-btn v-bind="attrs" small class="ml-1" color="info" v-on="on">
|
||||
{{ $t('project.actions.adminActions') }}
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-item :to="slug + '/flags'" nuxt>
|
||||
<v-list-item-title>
|
||||
{{ $t('project.actions.flagHistory', [project.info.flagCount]) }}
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item :to="slug + '/notes'" nuxt>
|
||||
<v-list-item-title>
|
||||
{{ $t('project.actions.staffNotes', [project.info.noteCount]) }}
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item :to="'/admin/log/?projectFilter=' + slug" nuxt>
|
||||
<v-list-item-title>
|
||||
{{ $t('project.actions.userActionLogs') }}
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item :href="$util.forumUrl(project.namespace.owner)">
|
||||
<v-list-item-title>
|
||||
{{ $t('project.actions.forum') }}
|
||||
<v-icon>mdi-open-in-new</v-icon>
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</v-col>
|
||||
<v-col cols="auto">
|
||||
<DonationModal
|
||||
v-if="project.settings.donation.enable"
|
||||
:donation-email="project.settings.donation.email"
|
||||
:default-amount="project.settings.donation.defaultAmount"
|
||||
:one-time-amounts="project.settings.donation.oneTimeAmounts"
|
||||
@ -39,35 +71,63 @@
|
||||
>
|
||||
<template #activator="{ on, attrs }">
|
||||
<v-btn v-bind="attrs" v-on="on">
|
||||
<v-icon left> mdi-currency-usd </v-icon>
|
||||
<v-icon left> mdi-currency-usd</v-icon>
|
||||
{{ $t('general.donate') }}
|
||||
</v-btn>
|
||||
</template>
|
||||
</DonationModal>
|
||||
</div>
|
||||
</DonationModal></v-col
|
||||
>
|
||||
|
||||
<v-col cols="auto">
|
||||
<v-btn v-if="!$util.isCurrentUser(project.owner.id)" @click="toggleStar">
|
||||
<v-icon v-if="project.userActions.starred" left color="amber"> mdi-star</v-icon>
|
||||
<v-icon v-else lef> mdi-star-outline</v-icon>
|
||||
<span v-if="project.userActions.starred">{{ $t('project.actions.unstar') }}</span>
|
||||
<span v-else>{{ $t('project.actions.star') }}</span>
|
||||
</v-btn>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="auto">
|
||||
<v-btn v-if="!$util.isCurrentUser(project.owner.id)" @click="toggleWatch">
|
||||
<v-icon v-if="project.userActions.watching" left> mdi-eye-off</v-icon>
|
||||
<v-icon v-else left> mdi-eye</v-icon>
|
||||
<span v-if="project.userActions.watching">{{ $t('project.actions.unwatch') }}</span>
|
||||
<span v-else>{{ $t('project.actions.watch') }}</span>
|
||||
</v-btn>
|
||||
</v-col>
|
||||
</v-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<v-divider class="mb-5" />
|
||||
|
||||
<div class="project-info">
|
||||
<p>{{ $t('project.category.info', [$store.state.projectCategories.get(project.category).title]) }}</p>
|
||||
<p>{{ $t('project.info.publishDate', [$util.prettyDate(project.createdAt)]) }}</p>
|
||||
<p v-if="project">
|
||||
<span id="view-count">{{ $tc('project.info.views', project.stats.views, [project.stats.views]) }}</span
|
||||
>, <span id="download-count"
|
||||
>{{ $tc('project.info.totalDownloads', project.stats.downloads, [project.stats.downloads]) }}
|
||||
</span>
|
||||
</p>
|
||||
<p v-if="project">
|
||||
<v-btn :to="`${$route.params.slug}/stars`" nuxt small>
|
||||
{{ $tc('project.info.stars', project.stats.stars, [project.stats.stars]) }}
|
||||
</v-btn>
|
||||
<v-btn :to="`${$route.params.slug}/watchers`" nuxt small>
|
||||
{{ $tc('project.info.watchers', project.stats.watchers, [project.stats.watchers]) }}
|
||||
</v-btn>
|
||||
</p>
|
||||
<div class="float-left">
|
||||
<p>{{ $t('project.category.info') }}</p>
|
||||
<p>{{ $t('project.info.publishDate') }}</p>
|
||||
<p>{{ $tc('project.info.views', project.stats.views) }}</p>
|
||||
<p>{{ $tc('project.info.totalDownloads', project.stats.downloads) }}</p>
|
||||
<NuxtLink :to="`${$route.params.slug}/stars`" nuxt small class="d-block">
|
||||
{{ $tc('project.info.stars', project.stats.stars) }}
|
||||
</NuxtLink>
|
||||
<NuxtLink :to="`${$route.params.slug}/watchers`" nuxt small class="d-block">
|
||||
{{ $tc('project.info.watchers', project.stats.watchers) }}
|
||||
</NuxtLink>
|
||||
<p v-if="project && project.settings.license && project.settings.license.name">
|
||||
{{ $t('project.license.link') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="float-right">
|
||||
<p>{{ $store.state.projectCategories.get(project.category).title }}</p>
|
||||
<p>{{ $util.prettyDate(project.createdAt) }}</p>
|
||||
<p>{{ project.stats.views }}</p>
|
||||
<p>{{ project.stats.downloads }}</p>
|
||||
<p>{{ project.stats.stars }}</p>
|
||||
<p>{{ project.stats.watchers }}</p>
|
||||
<p v-if="project && project.settings.license && project.settings.license.name">
|
||||
<a ref="noopener" :href="project.settings.license.url" target="_blank">{{ project.settings.license.name }}</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
@ -112,9 +172,19 @@ import DonationModal from '~/components/donation/DonationModal.vue';
|
||||
import { Markdown, MarkdownEditor } from '~/components/markdown';
|
||||
import { DocPageMixin } from '~/components/mixins';
|
||||
import { DownloadButton, MemberList, ProjectPageList } from '~/components/projects';
|
||||
import FlagModal from '~/components/modals/projects/FlagModal.vue';
|
||||
|
||||
@Component({
|
||||
components: { DownloadButton, ProjectPageList, Markdown, MemberList, DonationModal, MarkdownEditor, Tag },
|
||||
components: {
|
||||
FlagModal,
|
||||
DownloadButton,
|
||||
ProjectPageList,
|
||||
Markdown,
|
||||
MemberList,
|
||||
DonationModal,
|
||||
MarkdownEditor,
|
||||
Tag,
|
||||
},
|
||||
})
|
||||
export default class DocsPage extends DocPageMixin {
|
||||
roles!: Role[];
|
||||
@ -123,6 +193,28 @@ export default class DocsPage extends DocPageMixin {
|
||||
return process.env.publicHost;
|
||||
}
|
||||
|
||||
toggleStar() {
|
||||
this.$api
|
||||
.requestInternal<void>(`projects/project/${this.project.id}/star/${!this.project.userActions.starred}`, true, 'post')
|
||||
.then(() => {
|
||||
this.project.userActions.starred = !this.project.userActions.starred;
|
||||
})
|
||||
.catch((err) => this.$util.handleRequestError(err, 'project.error.star'));
|
||||
}
|
||||
|
||||
toggleWatch() {
|
||||
this.$api
|
||||
.requestInternal(`projects/project/${this.project.id}/watch/${!this.project.userActions.watching}`, true, 'post')
|
||||
.then(() => {
|
||||
this.project.userActions.watching = !this.project.userActions.watching;
|
||||
})
|
||||
.catch((err) => this.$util.handleRequestError(err, 'project.error.watch'));
|
||||
}
|
||||
|
||||
get slug(): string {
|
||||
return `/${this.project.namespace.owner}/${this.project.namespace.slug}`;
|
||||
}
|
||||
|
||||
async asyncData({ $api, params, $util }: Context) {
|
||||
const page = await $api.requestInternal<ProjectPage>(`pages/page/${params.author}/${params.slug}`, false).catch<any>($util.handlePageRequestError);
|
||||
const roles = await $api.requestInternal('data/projectRoles', false).catch($util.handlePageRequestError);
|
||||
@ -131,8 +223,22 @@ export default class DocsPage extends DocPageMixin {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.project-info p {
|
||||
<style lang="scss">
|
||||
.project-info {
|
||||
height: 170px; // no idea why I have to set a height...
|
||||
p {
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
.float-right p {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.flag-modal-trigger {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.main-page-content {
|
||||
padding-left: 25px;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-row>
|
||||
<v-col v-if="page.contents" cols="12" md="9">
|
||||
<v-col v-if="page.contents" cols="12" md="9" class="main-page-content">
|
||||
<MarkdownEditor
|
||||
v-if="$perms.canEditPage"
|
||||
ref="editor"
|
||||
@ -17,7 +16,6 @@
|
||||
<ProjectPageList :project="project" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
26
frontend/plugins/themes/base.ts
Normal file
26
frontend/plugins/themes/base.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import LRUCache from 'lru-cache';
|
||||
// @ts-ignore
|
||||
import minifyTheme from 'minify-css-string';
|
||||
import { ThemeOptions, VuetifyThemeCache, VuetifyThemeVariant } from 'vuetify/types/services/theme';
|
||||
|
||||
const themeCache = new LRUCache({
|
||||
max: 10,
|
||||
maxAge: 1000 * 60 * 60, // 1 hour
|
||||
}) as VuetifyThemeCache;
|
||||
|
||||
export default function buildTheme(darkTheme: boolean, dark: Partial<VuetifyThemeVariant>, light: Partial<VuetifyThemeVariant>): ThemeOptions {
|
||||
return {
|
||||
default: darkTheme ? 'dark' : 'light',
|
||||
dark: darkTheme,
|
||||
disable: false,
|
||||
options: {
|
||||
customProperties: true,
|
||||
themeCache,
|
||||
minifyTheme,
|
||||
},
|
||||
themes: {
|
||||
dark,
|
||||
light,
|
||||
},
|
||||
};
|
||||
}
|
15
frontend/plugins/themes/default_dark.ts
Normal file
15
frontend/plugins/themes/default_dark.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import colors from 'vuetify/es5/util/colors';
|
||||
import { VuetifyThemeVariant } from 'vuetify/types/services/theme';
|
||||
|
||||
export default {
|
||||
anchor: colors.blue.lighten3,
|
||||
primary: colors.blue.darken2,
|
||||
background: '#111827',
|
||||
box: '#212121',
|
||||
accent: '#272727',
|
||||
secondary: colors.amber.darken3,
|
||||
info: colors.lightBlue.base,
|
||||
warning: colors.orange.darken3,
|
||||
error: colors.deepOrange.accent4,
|
||||
success: colors.lightGreen.darken2,
|
||||
} as Partial<VuetifyThemeVariant>;
|
13
frontend/plugins/themes/default_light.ts
Normal file
13
frontend/plugins/themes/default_light.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import colors from 'vuetify/es5/util/colors';
|
||||
import { VuetifyThemeVariant } from 'vuetify/types/services/theme';
|
||||
|
||||
export default {
|
||||
anchor: colors.blue.lighten3,
|
||||
primary: colors.blue.darken2,
|
||||
accent: colors.grey.darken3,
|
||||
secondary: colors.amber.darken3,
|
||||
info: colors.teal.lighten1,
|
||||
warning: colors.amber.base,
|
||||
error: colors.deepOrange.accent4,
|
||||
success: colors.green.accent3,
|
||||
} as Partial<VuetifyThemeVariant>;
|
@ -1,6 +1,8 @@
|
||||
import colors from 'vuetify/es5/util/colors';
|
||||
import { VuetifyPreset } from 'vuetify';
|
||||
import { Paper, Velocity, Waterfall } from '~/components/logos';
|
||||
import buildTheme from '~/plugins/themes/base';
|
||||
import defaultDark from '~/plugins/themes/default_dark';
|
||||
import defaultLight from '~/plugins/themes/default_light';
|
||||
|
||||
export default {
|
||||
icons: {
|
||||
@ -17,34 +19,5 @@ export default {
|
||||
},
|
||||
},
|
||||
},
|
||||
theme: {
|
||||
default: 'dark',
|
||||
dark: true,
|
||||
disable: false,
|
||||
options: {
|
||||
customProperties: true,
|
||||
},
|
||||
themes: {
|
||||
dark: {
|
||||
anchor: colors.blue.lighten3,
|
||||
primary: colors.blue.darken2,
|
||||
accent: colors.grey.darken3,
|
||||
secondary: colors.amber.darken3,
|
||||
info: colors.lightBlue.base,
|
||||
warning: colors.orange.darken3,
|
||||
error: colors.deepOrange.accent4,
|
||||
success: colors.lightGreen.darken2,
|
||||
},
|
||||
light: {
|
||||
anchor: colors.blue.lighten3,
|
||||
primary: colors.blue.darken2,
|
||||
accent: colors.grey.darken3,
|
||||
secondary: colors.amber.darken3,
|
||||
info: colors.teal.lighten1,
|
||||
warning: colors.amber.base,
|
||||
error: colors.deepOrange.accent4,
|
||||
success: colors.green.accent3,
|
||||
},
|
||||
},
|
||||
},
|
||||
theme: buildTheme(true, defaultDark, defaultLight),
|
||||
} as Partial<VuetifyPreset>;
|
||||
|
@ -1834,6 +1834,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.168.tgz#fe24632e79b7ade3f132891afff86caa5e5ce008"
|
||||
integrity sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==
|
||||
|
||||
"@types/lru-cache@5.1.1":
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef"
|
||||
integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==
|
||||
|
||||
"@types/mime@^1":
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a"
|
||||
@ -6673,6 +6678,13 @@ lowlight@^1.17.0:
|
||||
fault "^1.0.0"
|
||||
highlight.js "~10.6.0"
|
||||
|
||||
lru-cache@6.0.0, lru-cache@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
|
||||
integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
lru-cache@^4.1.2:
|
||||
version "4.1.5"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
|
||||
@ -6688,13 +6700,6 @@ lru-cache@^5.1.1:
|
||||
dependencies:
|
||||
yallist "^3.0.2"
|
||||
|
||||
lru-cache@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
|
||||
integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
lru-queue@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3"
|
||||
@ -6910,6 +6915,11 @@ mimic-fn@^3.1.0:
|
||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74"
|
||||
integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==
|
||||
|
||||
minify-css-string@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/minify-css-string/-/minify-css-string-1.0.0.tgz#201bd949271e19f6e0af0a1dc0ccc583de47c630"
|
||||
integrity sha1-IBvZSSceGfbgrwodwMzFg95HxjA=
|
||||
|
||||
minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
|
||||
|
Loading…
Reference in New Issue
Block a user