Make Categories a predefined list

Signed-off-by: Thomas Citharel <tcit@tcit.fr>

Allow null values for categories for now

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2019-02-22 16:54:01 +01:00
parent 75554cd3f5
commit 7086fe8389
27 changed files with 89 additions and 655 deletions

View File

@@ -49,12 +49,6 @@ export default class App extends Vue {
route: "GroupList",
role: null
},
{
icon: "content_copy",
text: "Categories",
route: "CategoryList",
role: "ROLE_ADMIN"
},
{ icon: "settings", text: "Settings", role: "ROLE_USER" },
{ icon: "chat_bubble", text: "Send feedback", role: "ROLE_USER" },
{ icon: "help", text: "Help", role: null },

View File

@@ -1,29 +0,0 @@
import gql from 'graphql-tag';
export const FETCH_CATEGORIES = gql`
query {
categories {
id,
title,
description,
picture {
url,
},
}
}
`;
export const CREATE_CATEGORY = gql`
mutation createCategory($title: String!, $description: String!, $picture: Upload!) {
createCategory(title: $title, description: $description, picture: $picture) {
id,
title,
description,
picture {
url,
url_thumbnail
},
},
},
`;

View File

@@ -25,6 +25,7 @@ export const FETCH_EVENT = gql`
thumbnail,
large_image,
publish_at,
category,
# online_address,
# phone_address,
organizerActor {
@@ -39,10 +40,7 @@ export const FETCH_EVENT = gql`
# },
participants {
${participantQuery}
},
category {
title,
},
}
}
}
`;
@@ -75,9 +73,7 @@ export const FETCH_EVENTS = gql`
preferredUsername,
name,
},
category {
title,
},
category,
participants {
${participantQuery}
}
@@ -112,9 +108,9 @@ export const EDIT_EVENT = gql`
$title: String!,
$description: String!,
$organizerActorId: Int!,
$categoryId: Int!
$category: String!
) {
EditEvent(title: $title, description: $description, organizerActorId: $organizerActorId, categoryId: $categoryId) {
EditEvent(title: $title, description: $description, organizerActorId: $organizerActorId, category: $category) {
uuid
}
}

View File

@@ -1,22 +0,0 @@
import CategoryList from '@/views/Category/List.vue';
import CreateCategory from '@/views/Category/Create.vue';
export enum CategoryRouteName {
CATEGORY_LIST = 'CategoryList',
CREATE_CATEGORY = 'CreateCategory',
}
export const categoryRoutes = [
{
path: '/category',
name: CategoryRouteName.CATEGORY_LIST,
component: CategoryList,
meta: { requiredAuth: false },
},
{
path: '/category/create',
name: CategoryRouteName.CREATE_CATEGORY,
component: CreateCategory,
meta: { requiredAuth: true },
},
];

View File

@@ -5,7 +5,6 @@ import Home from '@/views/Home.vue';
import { UserRouteName, userRoutes } from './user';
import { EventRouteName, eventRoutes } from '@/router/event';
import { ActorRouteName, actorRoutes } from '@/router/actor';
import { CategoryRouteName, categoryRoutes } from '@/router/category';
Vue.use(Router);
@@ -20,7 +19,6 @@ export const RouteName = {
...GlobalRouteName,
...UserRouteName,
...EventRouteName,
...CategoryRouteName,
...ActorRouteName,
};
@@ -30,7 +28,6 @@ const router = new Router({
routes: [
...userRoutes,
...eventRoutes,
...categoryRoutes,
...actorRoutes,
{

View File

@@ -27,10 +27,12 @@ export enum ParticipantRole {
CREATOR = 'creator',
}
export interface ICategory {
title: string;
description: string;
picture: string;
export enum Category {
BUSINESS = 'business',
CONFERENCE = 'conference',
BIRTHDAY = 'birthday',
DEMONSTRATION = 'demonstration',
MEETING = 'meeting',
}
export interface IParticipant {
@@ -47,7 +49,7 @@ export interface IEvent {
title: string;
description: string;
category: ICategory;
category: Category;
begins_on: Date;
ends_on: Date;

View File

@@ -1,75 +0,0 @@
<template>
<section>
<h1 class="title">
<translate>Create a new category</translate>
</h1>
<div class="columns">
<form class="column" @submit="submit">
<b-field :label="$gettext('Name of the category')">
<b-input aria-required="true" required v-model="category.title"/>
</b-field>
<b-field :label="$gettext('Description')">
<b-input type="textarea" v-model="category.description"/>
</b-field>
<b-field class="file">
<b-upload v-model="file" @input="onFilePicked">
<a class="button is-primary">
<b-icon icon="upload"></b-icon>
<span>
<translate>Click to upload</translate>
</span>
</a>
</b-upload>
<span class="file-name" v-if="file">{{ this.image.name }}</span>
</b-field>
<button class="button is-primary">
<translate>Create the category</translate>
</button>
</form>
</div>
</section>
</template>
<script lang="ts">
import { CREATE_CATEGORY } from "@/graphql/category";
import { Component, Vue } from "vue-property-decorator";
import { ICategory } from "@/types/event.model";
/**
* TODO : No picture is uploaded ATM
*/
@Component
export default class CreateCategory extends Vue {
category!: ICategory;
image = {
name: ""
} as { name: string };
file: any = null;
create() {
this.$apollo
.mutate({
mutation: CREATE_CATEGORY,
variables: this.category
})
.then(data => {
console.log(data);
})
.catch(error => {
console.error(error);
});
}
// TODO : Check if we can upload as soon as file is picked and purge files not validated
onFilePicked(e) {
if (e === undefined || e.name.lastIndexOf(".") <= 0) {
console.error("File is incorrect");
}
this.image.name = e.name;
}
}
</script>

View File

@@ -1,55 +0,0 @@
<template>
<section>
<h1 class="title">
<translate>Category List</translate>
</h1>
<b-loading :active.sync="$apollo.loading"></b-loading>
<div class="columns">
<div class="column card" v-for="category in categories" :key="category.id">
<div class="card-image">
<figure class="image is-4by3">
<img v-if="category.picture.url" :src="HTTP_ENDPOINT + category.picture.url">
</figure>
</div>
<div class="card-content">
<h2 class="title is-4">{{ category.title }}</h2>
<p>{{ category.description }}</p>
</div>
</div>
</div>
</section>
</template>
<script lang="ts">
import { FETCH_CATEGORIES } from "@/graphql/category";
import { Component, Vue } from "vue-property-decorator";
// TODO : remove this hardcode
@Component({
apollo: {
categories: {
query: FETCH_CATEGORIES
}
}
})
export default class List extends Vue {
categories = [];
loading = true;
HTTP_ENDPOINT = "http://localhost:4000";
deleteCategory(categoryId) {
const router = this.$router;
// FIXME: remove eventFetch
// eventFetch(`/categories/${categoryId}`, this.$store, { method: 'DELETE' })
// .then(() => {
// this.categories = this.categories.filter(category => category.id !== categoryId);
// router.push('/category');
// });
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

View File

@@ -1,3 +1,4 @@
import {Category} from "../../types/event.model";
import {EventJoinOptions} from "../../types/event.model";
<template>
<section>
@@ -18,8 +19,8 @@ import {EventJoinOptions} from "../../types/event.model";
<option
v-for="category in categories"
:value="category"
:key="category.title"
>{{ category.title }}</option>
:key="category"
>{{ $gettext(category) }}</option>
</b-select>
</b-field>
@@ -32,30 +33,24 @@ import {EventJoinOptions} from "../../types/event.model";
</template>
<script lang="ts">
// import Location from '@/components/Location';
import VueMarkdown from "vue-markdown";
import {CREATE_EVENT, EDIT_EVENT} from "@/graphql/event";
import {FETCH_CATEGORIES} from "@/graphql/category";
import {Component, Prop, Vue} from "vue-property-decorator";
import {EventJoinOptions, EventStatus, EventVisibility, ICategory, IEvent} from "@/types/event.model";
import {LOGGED_PERSON} from "@/graphql/actor";
import {IPerson} from "@/types/actor.model";
// import Location from '@/components/Location';
import VueMarkdown from "vue-markdown";
import {CREATE_EVENT, EDIT_EVENT} from "@/graphql/event";
import {Component, Prop, Vue} from "vue-property-decorator";
import {Category, EventJoinOptions, EventStatus, EventVisibility, IEvent} from "@/types/event.model";
import {LOGGED_PERSON} from "@/graphql/actor";
import {IPerson} from "@/types/actor.model";
@Component({
@Component({
components: {
VueMarkdown
},
apollo: {
categories: {
query: FETCH_CATEGORIES
}
}
})
export default class CreateEvent extends Vue {
@Prop({ required: false, type: String }) uuid!: string;
loggedPerson!: IPerson;
categories: ICategory[] = [];
categories: string[] = Object.keys(Category);
event!: IEvent; // FIXME: correctly type an event
// created() {
@@ -77,7 +72,7 @@ export default class CreateEvent extends Vue {
description: "",
begins_on: new Date(),
ends_on: new Date(),
category: this.categories[0],
category: Category.MEETING,
participants: [],
uuid: "",
url: "",
@@ -102,7 +97,7 @@ export default class CreateEvent extends Vue {
title: this.event.title,
description: this.event.description,
beginsOn: this.event.begins_on,
category: this.event.category.title,
category: this.event.category,
organizerActorId: this.event.organizerActor.id
}
})

View File

@@ -10,7 +10,7 @@
</div>
<div class="card-content">
<span>{{ event.begins_on | formatDay }}</span>
<span class="tag is-primary">{{ event.category.title }}</span>
<span class="tag is-primary">{{ event.category }}</span>
<h1 class="title">{{ event.title }}</h1>
<router-link
:to="{name: 'Profile', params: { name: event.organizerActor.preferredUsername } }"