bunch of unfinished stuff

This commit is contained in:
MiniDigger 2021-02-08 21:45:54 +01:00
parent 7b25ae4b95
commit e67b897535
12 changed files with 460 additions and 10 deletions

View File

@ -0,0 +1,16 @@
<template>
<div>
<!-- todo editor -->
{{ $route.name }}
hur dur am a editor
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator';
@Component
export default class Editor extends Vue {}
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,12 @@
<template>
<!-- todo memberlist -->
<div>Memberlist</div>
</template>
<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator';
@Component({})
export default class MemberList extends Vue {}
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,33 @@
<template>
<div class="tags" :class="{ 'has-addons': data }">
<span
:style="{
color: color.foreground,
background: color.background,
'border-color': color.background,
}"
class="tag"
>
{{ name }}
</span>
<span v-if="data" class="tag">{{ data }}</span>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator';
import { Prop } from 'vue-property-decorator';
@Component({})
export default class DocsPage extends Vue {
@Prop()
name!: String;
@Prop()
data!: String;
@Prop()
color!: Object;
}
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,121 @@
<template>
<!-- todo fix the layout of this modal, some buttons and shit, also i18n, also am tired -->
<v-dialog v-model="show">
<template #activator="{ on, attrs }">
<slot name="activator" :on="on" :attrs="attrs" />
</template>
<v-card>
<v-card-title>
<h4>Donate to ....</h4>
<v-btn @click="show = false">&times;</v-btn>
</v-card-title>
<v-card-text>
<v-row>
<v-col cols="12">
<button type="button" :class="'btn ' + (monthly ? 'btn-primary' : 'btn-default')" @click="monthly = true">Monthly</button>
<button type="button" :class="'btn ' + (monthly ? 'btn-default' : 'btn-primary')" @click="monthly = false">One-Time</button>
</v-col>
</v-row>
<form action="https://sandbox.paypal.com/cgi-bin/webscr" method="post" @submit="popup($el)">
<!-- https://developer.paypal.com/docs/paypal-payments-standard/integration-guide/Appx-websitestandard-htmlvariables/ -->
<input type="hidden" name="business" :value="donationEmail" />
<input type="hidden" name="return" :value="returnUrl" />
<input type="hidden" name="cancel_return" :value="cancelReturnUrl" />
<!-- return method, 2 = POST, with all variables -->
<input type="hidden" name="rm" value="1" />
<input type="hidden" name="item_name" :value="'Hangar: ' + (monthly ? 'Monthly ' : 'One-Time ') + 'Donation to ' + donationTarget" />
<input type="hidden" name="quantity" value="1" />
<!-- locale -->
<input type="hidden" name="lc" value="US" />
<input type="hidden" name="currency_code" value="USD" />
<input type="hidden" name="charset" value="utf-8" />
<input type="hidden" name="notify_url" value="https://hangar.minidigger.me/paypal/ipn" />
<input type="hidden" name="custom" value="idk, maybe hangar user id?" />
<template v-if="monthly">
<input type="hidden" name="cmd" value="_xclick-subscriptions" />
<input type="hidden" name="bn" :value="'Hangar_Subscribe_' + donationTarget + 'US'" />
<input type="hidden" name="no_note" value="1" />
<!-- 1 = do not prompt for an address -->
<input type="hidden" name="no_shipping" value="1" />
<!-- recurring -->
<input type="hidden" name="src" value="1" />
<!-- p3 + t3 = 1 month -->
<input type="hidden" name="p3" value="1" />
<input type="hidden" name="t3" value="M" />
</template>
<template v-else>
<input type="hidden" name="cmd" value="_donations" />
<input type="hidden" name="bn" :value="'Hangar_Donate_' + donationTarget + 'US'" />
</template>
<v-row>
<v-col cols="12">
<button
v-for="a in monthly ? monthlyAmounts : oneTimeAmounts"
:key="a"
:class="'btn ' + (amount === a ? 'btn-primary' : 'btn-default')"
@click.prevent="amount = a"
>
${{ a }}
</button>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<div>Select an amount above or enter an amount below</div>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<div class="input-group mb-3">
<input v-model="amount" type="number" class="form-control" :name="monthly ? 'a3' : 'amount'" />
<span class="input-group-text">USD</span>
</div>
<small class="form-text">By donating to X you agree to Y and that tacos are delicious</small>
<div>
<input type="submit" :value="'Donate ' + (monthly ? 'Monthly ' : 'One-Time ')" class="btn btn-primary" />
<img alt="" width="1" height="1" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" />
</div>
</v-col>
</v-row>
</form>
</v-card-text>
<v-card-actions>
<v-btn @click="show = false">Close</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator';
import { Prop } from 'vue-property-decorator';
@Component({})
export default class DonationModal extends Vue {
monthly: boolean = true;
amount: number = 20;
show: boolean = false;
@Prop({ required: true })
donationTarget!: String;
@Prop({ required: true })
donationEmail!: String;
@Prop({ required: true })
returnUrl!: String;
@Prop({ required: true })
cancelReturnUrl!: String;
oneTimeAmounts: Array<number> = [10, 20, 30];
monthlyAmounts: Array<number> = [5, 10, 15, 20];
}
</script>
<style scoped></style>

View File

@ -0,0 +1,39 @@
<template>
<div v-if="qs['donation']" class="row">
<div class="col-12">
<Announcement :announcement="announcement"></Announcement>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator';
import Announcement from '~/components/layouts/Announcement.vue';
@Component({
components: { Announcement },
})
export default class DonationResult extends Vue {
get qs() {
return this.$route.query;
}
get announcement() {
let text = '';
if (this.qs.donation && this.qs.donation === 'success' && this.qs.st && this.qs.st === 'Completed') {
text = 'Donation successful! You donated ' + this.qs.amt + ' ' + this.qs.cc + ' ' + this.qs.item_name;
} else if (this.qs.donation && this.qs.donation === 'failure') {
text = 'Donation failed.';
} else {
text = JSON.stringify(this.qs);
}
return {
text,
color: '#093962',
};
}
}
</script>
<style scoped></style>

View File

@ -12,6 +12,9 @@
</template>
<Dropdown :controls="dropdown" />
</v-menu>
<v-spacer></v-spacer>
<v-menu v-if="$util.isLoggedIn()" bottom offset-y transition="slide-y-transition">
<template #activator="{ on, attrs }">
<v-btn v-bind="attrs" color="primary" v-on="on">
@ -21,8 +24,6 @@
<Dropdown :controls="newControls" />
</v-menu>
<v-spacer></v-spacer>
<v-tooltip bottom>
<template #activator="{ on }">
<v-btn icon to="/authors" nuxt v-on="on"><v-icon>mdi-account-group</v-icon></v-btn>

View File

@ -0,0 +1,50 @@
<template>
<div>
<!-- todo fix this -->
<div class="modal-header">
<h4 v-show="!newPage.error" id="new-page-label" class="modal-title" v-text="$t('page.new.title')"></h4>
<h4 v-show="newPage.error" id="new-page-label-error" class="modal-title" v-text="$t('page.new.error')"></h4>
<button type="button" class="close" data-dismiss="modal" :aria-label="$t('general.close')">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body input-group">
<div class="setting">
<div class="setting-description">
<h4 v-text="$t('project.page.name._')"></h4>
<p v-text="$t('project.page.name.info')"></p>
</div>
<div class="setting-content">
<label for="page-name" class="sr-only">Page Name</label>
<input id="page-name" v-model="newPage.pageName" class="form-control" type="text" />
</div>
<div class="clearfix"></div>
</div>
<div class="setting setting-no-border">
<div class="setting-description">
<h4 v-text="$t('project.page.parent._')"></h4>
<p v-text="$t('project.page.parent.info')"></p>
</div>
<div class="setting-content">
<label for="new-page-parent-select" class="sr-only"></label>
<select id="new-page-parent-select" v-model="newPage.parentPage" class="form-control select-parent">
<option disabled hidden :value="null">&lt;none&gt;</option>
<option v-for="pg in noHomePage(rootPages)" :key="pg.id" :value="{ id: pg.id, slug: pg.slug }" v-text="pg.name"></option>
</select>
</div>
<div class="clearfix"></div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal" v-text="$t('general.close')"></button>
<button id="continue-page" type="button" class="btn btn-primary" @click="createPage" v-text="$t('general.continue')"></button>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator';
@Component
export default class NewPageModal extends Vue {}
</script>

View File

@ -5,6 +5,7 @@
<v-container>
<Announcement v-for="(announcement, idx) in announcements" :key="idx" :announcement="announcement" />
<DonationResult />
<nuxt />
</v-container>
</v-main>
@ -19,9 +20,11 @@ import Header from '~/components/layouts/Header.vue';
import Footer from '~/components/layouts/Footer.vue';
import Announcement from '~/components/layouts/Announcement.vue';
import HangarSnackbar from '~/components/layouts/HangarSnackbar.vue';
import DonationResult from '~/components/donation/DonationResult.vue';
@Component({
components: {
DonationResult,
Header,
Footer,
Announcement,

View File

@ -5,6 +5,7 @@ const msgs: LocaleMessageObject = {
close: 'Close',
submit: 'Submit',
comment: 'Comment',
donate: 'Donate',
},
hangar: {
projectSearch: {
@ -50,6 +51,7 @@ const msgs: LocaleMessageObject = {
},
project: {
category: {
info: 'Category: {0}',
admin_tools: 'Admin Tools',
chat: 'Chat',
dev_tools: 'Developer Tools',
@ -136,6 +138,16 @@ const msgs: LocaleMessageObject = {
error: 'There was an error creating the project',
},
sendForApproval: 'Send for approval',
info: 'Information',
publishDate: 'Published on {0}',
views: '{0} views',
promotedVersions: 'Promoted Versions',
license: {
link: 'Licensed under ',
},
},
page: {
plural: 'Pages',
},
organization: {
new: {

View File

@ -154,7 +154,6 @@ export default class ProjectPage extends Vue {
const tabs = [] as Tab[];
tabs.push({ title: this.$t('project.tabs.docs') as String, icon: 'mdi-book', link: this.slug, external: false });
tabs.push({ title: this.$t('project.tabs.versions') as String, icon: 'mdi-download', link: this.slug + '/versions', external: false });
// todo check if has a discussion
if (this.project.settings.forumSync) {
tabs.push({ title: this.$t('project.tabs.discuss') as String, icon: 'mdi-account-group', link: this.slug + '/discuss', external: false });
}

View File

@ -1,14 +1,162 @@
<template>
<div>
{{ $route.name }}
</div>
<v-row>
<v-col cols="12" md="8">
<Editor />
</v-col>
<v-col cols="12" md="4">
<v-row>
<v-col cols="12">
<v-card>
<v-card-title v-text="$t('project.info')"></v-card-title>
<v-card-text>
<!-- todo where do we get this from? -->
<v-btn-toggle v-if="project.recommendedVersionId">
<v-btn>
<v-icon>mdi-download-outline</v-icon>
{{ $t('general.download') }}
</v-btn>
<v-btn>
<v-icon>mdi-content-copy</v-icon>
</v-btn>
</v-btn-toggle>
<!-- todo: make donation button toggleable in settings, get email and stuff into modal, translate -->
<div v-if="true">
<DonationModal
donation-email="minidigger-author@hangar.minidigger.me"
donation-target="paper/Test"
return-url="http://localhost:8080/paper/Test?donation=success"
cancel-return-url="http://localhost:8080/paper/Test?donation=failure"
>
<template #activator="{ on, attrs }">
<v-btn v-bind="attrs" v-on="on">
<v-icon>mdi-currency-usd</v-icon>
{{ $t('general.donate') }}
</v-btn>
</template>
</DonationModal>
</div>
<div>
<p>{{ $t('project.category.info', [formatCategory(project.category)]) }}</p>
<p>{{ $t('project.publishDate', [$util.prettyDate(project.createdAt)]) }}</p>
<p v-if="project">
<span id="view-count">{{ $t('project.views', [project.stats.views]) }}</span>
</p>
<p v-if="project">
<span id="star-count">{{ project.stats.stars }}</span>
<NuxtLink :to="project.namespace.slug + '/stars'">
{{ project.stats.views !== 1 ? ' stars' : ' star' }}
</NuxtLink>
</p>
<p v-if="project">
<span id="watcher-count">{{ project.stats.watchers }}</span>
<NuxtLink :to="project.namespace.slug + '/watchers'">
{{ project.stats.views !== 1 ? ' watchers' : ' watcher' }}
</NuxtLink>
</p>
<p v-if="project">
<span id="download-count">{{ project.stats.downloads }} total download{{ project.stats.downloads !== 1 ? 's' : '' }}</span>
</p>
<p v-if="project && project.settings.license">
{{ $t('project.license.link') }}
<a ref="noopener" :href="project.settings.license.url" target="_blank">{{ project.settings.license.name }}</a>
</p>
</div>
</v-card-text>
</v-card>
</v-col>
<v-col cols="12">
<v-card>
<v-card-title v-text="$t('project.promotedVersions')"></v-card-title>
<v-card-text>
<v-list v-if="project">
<v-list-item v-for="(version, index) in project.promotedVersions" :key="`${index}-${version.version}`">
{{ version.version.substring(0, version.version.lastIndexOf('.')) }}
<Tag v-for="(tag, idx) in version.tags" :key="idx" :color="tag.color" :data="tag.displayData" :name="tag.name"></Tag>
</v-list-item>
</v-list>
<div v-else class="text-center py-4">
<v-progress-circular indeterminate />
</div>
</v-card-text>
</v-card>
</v-col>
<v-col cols="12">
<v-card>
<v-card-title>
{{ $t('page.plural') }}
<!-- todo new page modal -->
<v-btn icon><v-icon>mdi-plus</v-icon></v-btn>
</v-card-title>
<v-card-text>
<v-list v-if="rootPages">
<v-list-item v-for="page in rootPages" :key="page.id"> </v-list-item>
</v-list>
<div v-else class="text-center py-4">
<v-progress-circular indeterminate />
</div>
</v-card-text>
</v-card>
</v-col>
<!-- todo member list -->
<v-col cols="12">
<MemberList />
<!-- <MemberList-->
<!-- :filtered-members-prop="filteredMembers"-->
<!-- :can-manage-members="canManageMembers"-->
<!-- :settings-call="ROUTES.parse('PROJECTS_SHOW_SETTINGS', project.ownerName, project.slug)"-->
<!-- ></MemberList>-->
</v-col>
</v-row>
</v-col>
</v-row>
</template>
<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator';
import { Page, Project } from 'hangar-api';
import { HangarProject } from 'hangar-internal';
import { Context } from '@nuxt/types';
import Editor from '~/components/Editor.vue';
import Tag from '~/components/Tag.vue';
import DonationModal from '~/components/donation/DonationModal.vue';
import MemberList from '~/components/MemberList.vue';
@Component({
components: { MemberList, DonationModal, Editor, Tag },
})
export default class DocsPage extends Vue {
project!: Project;
rootPages: Array<Page> = [];
@Component
export default class DocsPage extends Vue {}
async asyncData({ $api, params, $util }: Context) {
const project = await $api
.requestInternal<HangarProject>(`projects/project/${params.author}/${params.slug}`, false)
.catch($util.handlePageRequestError);
// todo add new route
// const rootPages = await $api
// .requestInternal<HangarProject>(`projects/project/${params.author}/${params.slug}`, false)
// .catch($util.handlePageRequestError);
return {
project,
// rootPages,
};
}
formatCategory(apiName: string) {
const formatted = apiName.replace('_', ' ');
return this.capitalize(formatted);
}
capitalize(input: string) {
return input
.toLowerCase()
.split(' ')
.map((s: string) => s.charAt(0).toUpperCase() + s.substring(1))
.join(' ');
}
}
</script>
<style lang="scss" scoped></style>

View File

@ -65,7 +65,7 @@ declare module 'hangar-api' {
recentViews: number;
recentDownloads: number;
stars: number;
waters: number;
watchers: number;
}
interface UserActions {
@ -73,12 +73,17 @@ declare module 'hangar-api' {
watching: boolean;
}
interface Licence {
name: string | null;
url: string | null;
}
interface ProjectSettings {
homepage: string | null;
issues: string | null;
sources: string | null;
support: string | null;
license: string | null;
license: Licence | null;
forumSync: boolean;
}
@ -134,4 +139,15 @@ declare module 'hangar-api' {
permissionBinString: string;
permissions: IPermission[];
}
interface Page {
id: number;
createdAt: string;
projectId: number;
name: string;
slug: string;
isDeletable: false;
contents: string;
children: Array<Page>;
}
}