summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/work_items
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/work_items')
-rw-r--r--app/assets/javascripts/work_items/components/app.vue10
-rw-r--r--app/assets/javascripts/work_items/constants.js3
-rw-r--r--app/assets/javascripts/work_items/graphql/fragmentTypes.json1
-rw-r--r--app/assets/javascripts/work_items/graphql/provider.js55
-rw-r--r--app/assets/javascripts/work_items/graphql/resolvers.js0
-rw-r--r--app/assets/javascripts/work_items/graphql/typedefs.graphql38
-rw-r--r--app/assets/javascripts/work_items/graphql/widget.fragment.graphql3
-rw-r--r--app/assets/javascripts/work_items/graphql/work_item.query.graphql16
-rw-r--r--app/assets/javascripts/work_items/index.js4
-rw-r--r--app/assets/javascripts/work_items/pages/work_item_root.vue48
-rw-r--r--app/assets/javascripts/work_items/router/index.js14
-rw-r--r--app/assets/javascripts/work_items/router/routes.js8
12 files changed, 193 insertions, 7 deletions
diff --git a/app/assets/javascripts/work_items/components/app.vue b/app/assets/javascripts/work_items/components/app.vue
index 93de17d1e43..a14d0c32cbe 100644
--- a/app/assets/javascripts/work_items/components/app.vue
+++ b/app/assets/javascripts/work_items/components/app.vue
@@ -1,9 +1,5 @@
-<script>
-export default {
- name: 'WorkItemRoot',
-};
-</script>
-
<template>
- <div></div>
+ <div>
+ <router-view />
+ </div>
</template>
diff --git a/app/assets/javascripts/work_items/constants.js b/app/assets/javascripts/work_items/constants.js
new file mode 100644
index 00000000000..b39f68abf74
--- /dev/null
+++ b/app/assets/javascripts/work_items/constants.js
@@ -0,0 +1,3 @@
+export const widgetTypes = {
+ title: 'TITLE',
+};
diff --git a/app/assets/javascripts/work_items/graphql/fragmentTypes.json b/app/assets/javascripts/work_items/graphql/fragmentTypes.json
new file mode 100644
index 00000000000..c048ac34ac0
--- /dev/null
+++ b/app/assets/javascripts/work_items/graphql/fragmentTypes.json
@@ -0,0 +1 @@
+{"__schema":{"types":[{"kind":"INTERFACE","name":"WorkItemWidget","possibleTypes":[{"name":"TitleWidget"}]}]}}
diff --git a/app/assets/javascripts/work_items/graphql/provider.js b/app/assets/javascripts/work_items/graphql/provider.js
new file mode 100644
index 00000000000..083735336ce
--- /dev/null
+++ b/app/assets/javascripts/work_items/graphql/provider.js
@@ -0,0 +1,55 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
+import createDefaultClient from '~/lib/graphql';
+import workItemQuery from './work_item.query.graphql';
+import introspectionQueryResultData from './fragmentTypes.json';
+import typeDefs from './typedefs.graphql';
+
+const fragmentMatcher = new IntrospectionFragmentMatcher({
+ introspectionQueryResultData,
+});
+
+export function createApolloProvider() {
+ Vue.use(VueApollo);
+
+ const defaultClient = createDefaultClient(
+ {},
+ {
+ cacheConfig: {
+ fragmentMatcher,
+ },
+ typeDefs,
+ },
+ );
+
+ defaultClient.cache.writeQuery({
+ query: workItemQuery,
+ variables: {
+ id: '1',
+ },
+ data: {
+ workItem: {
+ __typename: 'WorkItem',
+ id: '1',
+ type: 'FEATURE',
+ widgets: {
+ __typename: 'WorkItemWidgetConnection',
+ nodes: [
+ {
+ __typename: 'TitleWidget',
+ type: 'TITLE',
+ enabled: true,
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ contentText: 'Test Work Item Title',
+ },
+ ],
+ },
+ },
+ },
+ });
+
+ return new VueApollo({
+ defaultClient,
+ });
+}
diff --git a/app/assets/javascripts/work_items/graphql/resolvers.js b/app/assets/javascripts/work_items/graphql/resolvers.js
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/app/assets/javascripts/work_items/graphql/resolvers.js
diff --git a/app/assets/javascripts/work_items/graphql/typedefs.graphql b/app/assets/javascripts/work_items/graphql/typedefs.graphql
index e69de29bb2d..4a6e4aeed60 100644
--- a/app/assets/javascripts/work_items/graphql/typedefs.graphql
+++ b/app/assets/javascripts/work_items/graphql/typedefs.graphql
@@ -0,0 +1,38 @@
+enum WorkItemType {
+ FEATURE
+}
+
+enum WidgetType {
+ TITLE
+}
+
+interface WorkItemWidget {
+ type: WidgetType!
+}
+
+# Replicating Relay connection type for client schema
+type WorkItemWidgetEdge {
+ cursor: String!
+ node: WorkItemWidget
+}
+
+type WorkItemWidgetConnection {
+ edges: [WorkItemWidgetEdge]
+ nodes: [WorkItemWidget]
+ pageInfo: PageInfo!
+}
+
+type TitleWidget implements WorkItemWidget {
+ type: WidgetType!
+ contentText: String!
+}
+
+type WorkItem {
+ id: ID!
+ type: WorkItemType!
+ widgets: [WorkItemWidgetConnection]
+}
+
+extend type Query {
+ workItem(id: ID!): WorkItem!
+}
diff --git a/app/assets/javascripts/work_items/graphql/widget.fragment.graphql b/app/assets/javascripts/work_items/graphql/widget.fragment.graphql
new file mode 100644
index 00000000000..d7608c26052
--- /dev/null
+++ b/app/assets/javascripts/work_items/graphql/widget.fragment.graphql
@@ -0,0 +1,3 @@
+fragment WidgetBase on WorkItemWidget {
+ type
+}
diff --git a/app/assets/javascripts/work_items/graphql/work_item.query.graphql b/app/assets/javascripts/work_items/graphql/work_item.query.graphql
new file mode 100644
index 00000000000..549e4f8c65a
--- /dev/null
+++ b/app/assets/javascripts/work_items/graphql/work_item.query.graphql
@@ -0,0 +1,16 @@
+#import './widget.fragment.graphql'
+
+query WorkItem($id: ID!) {
+ workItem(id: $id) @client {
+ id
+ type
+ widgets {
+ nodes {
+ ...WidgetBase
+ ... on TitleWidget {
+ contentText
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/work_items/index.js b/app/assets/javascripts/work_items/index.js
index a635d43776d..7cc8a23b7b1 100644
--- a/app/assets/javascripts/work_items/index.js
+++ b/app/assets/javascripts/work_items/index.js
@@ -1,11 +1,15 @@
import Vue from 'vue';
import App from './components/app.vue';
+import { createRouter } from './router';
+import { createApolloProvider } from './graphql/provider';
export const initWorkItemsRoot = () => {
const el = document.querySelector('#js-work-items');
return new Vue({
el,
+ router: createRouter(el.dataset.fullPath),
+ apolloProvider: createApolloProvider(),
render(createElement) {
return createElement(App);
},
diff --git a/app/assets/javascripts/work_items/pages/work_item_root.vue b/app/assets/javascripts/work_items/pages/work_item_root.vue
new file mode 100644
index 00000000000..493ee0aba01
--- /dev/null
+++ b/app/assets/javascripts/work_items/pages/work_item_root.vue
@@ -0,0 +1,48 @@
+<script>
+import workItemQuery from '../graphql/work_item.query.graphql';
+import { widgetTypes } from '../constants';
+
+export default {
+ props: {
+ id: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ workItem: null,
+ };
+ },
+ apollo: {
+ workItem: {
+ query: workItemQuery,
+ variables() {
+ return {
+ id: this.id,
+ };
+ },
+ },
+ },
+ computed: {
+ titleWidgetData() {
+ return this.workItem?.widgets?.nodes?.find((widget) => widget.type === widgetTypes.title);
+ },
+ },
+};
+</script>
+
+<template>
+ <section>
+ <!-- Title widget placeholder -->
+ <div>
+ <h2
+ v-if="titleWidgetData"
+ class="gl-font-weight-normal gl-sm-font-weight-bold gl-my-5"
+ data-testid="title"
+ >
+ {{ titleWidgetData.contentText }}
+ </h2>
+ </div>
+ </section>
+</template>
diff --git a/app/assets/javascripts/work_items/router/index.js b/app/assets/javascripts/work_items/router/index.js
new file mode 100644
index 00000000000..142fab8cfa6
--- /dev/null
+++ b/app/assets/javascripts/work_items/router/index.js
@@ -0,0 +1,14 @@
+import Vue from 'vue';
+import VueRouter from 'vue-router';
+import { joinPaths } from '~/lib/utils/url_utility';
+import { routes } from './routes';
+
+Vue.use(VueRouter);
+
+export function createRouter(fullPath) {
+ return new VueRouter({
+ routes,
+ mode: 'history',
+ base: joinPaths(fullPath, '-', 'work_items'),
+ });
+}
diff --git a/app/assets/javascripts/work_items/router/routes.js b/app/assets/javascripts/work_items/router/routes.js
new file mode 100644
index 00000000000..a3cf44ad4ca
--- /dev/null
+++ b/app/assets/javascripts/work_items/router/routes.js
@@ -0,0 +1,8 @@
+export const routes = [
+ {
+ path: '/:id',
+ name: 'work_item',
+ component: () => import('../pages/work_item_root.vue'),
+ props: true,
+ },
+];