Commit 25f9a50a authored by Enrique Alcantara's avatar Enrique Alcantara

Add file client-side resolver

Create a client-side resolver to
retrieve a file content using the GraphQL
API

Use the file client-side resolver
to fetch the page source content
parent f2a60225
import { s__ } from '~/locale';
import { s__, __ } from '~/locale';
export const BRANCH_SUFFIX_COUNT = 8;
export const DEFAULT_TARGET_BRANCH = 'master';
......@@ -10,5 +10,8 @@ export const SUBMIT_CHANGES_COMMIT_ERROR = s__(
export const SUBMIT_CHANGES_MERGE_REQUEST_ERROR = s__(
'StaticSiteEditor|Could not create merge request.',
);
export const LOAD_CONTENT_ERROR = __(
'An error ocurred while loading your content. Please try again.',
);
export const DEFAULT_HEADING = s__('StaticSiteEditor|Static site editor');
......@@ -3,18 +3,29 @@ import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import typeDefs from './typedefs.graphql';
import fileResolver from './resolvers/file';
Vue.use(VueApollo);
const createApolloProvider = data => {
const createApolloProvider = appData => {
const defaultClient = createDefaultClient(
{},
{
Project: {
file: fileResolver,
},
},
{
typeDefs,
},
);
defaultClient.cache.writeData({
data,
data: {
appData: {
__typename: 'AppData',
...appData,
},
},
});
return new VueApollo({
......
query appData {
isSupportedContent @client
appData @client {
isSupportedContent
project
sourcePath
returnUrl
}
}
query sourceContent($project: ID!, $sourcePath: String!) {
project(fullPath: $project) {
fullPath,
file(path: $sourcePath) @client {
title
content
}
}
}
import loadSourceContent from '../../services/load_source_content';
const fileResolver = ({ fullPath: projectId }, { path: sourcePath }) => {
return loadSourceContent({ projectId, sourcePath }).then(sourceContent => ({
// eslint-disable-next-line @gitlab/require-i18n-strings
__typename: 'File',
...sourceContent,
}));
};
export default fileResolver;
extend type Query {
type File {
title: String
content: String!
}
extend type Project {
file(path: ID!): File
}
type AppData {
isSupportedContent: Boolean!
project: String!
returnUrl: String
sourcePath: String!
username: String!
}
extend type Query {
appData: AppData!
}
......@@ -12,6 +12,11 @@ import InvalidContentMessage from '../components/invalid_content_message.vue';
import SubmitChangesError from '../components/submit_changes_error.vue';
import appDataQuery from '../graphql/queries/app_data.query.graphql';
import sourceContentQuery from '../graphql/queries/source_content.query.graphql';
import createFlash from '~/flash';
import { LOAD_CONTENT_ERROR } from '../constants';
export default {
components: {
......@@ -26,9 +31,31 @@ export default {
},
mixins: [glFeatureFlagsMixin()],
apollo: {
isSupportedContent: {
appData: {
query: appDataQuery,
},
sourceContent: {
query: sourceContentQuery,
update: ({
project: {
file: { title, content },
},
}) => {
return { title, content };
},
variables() {
return {
project: this.appData.project,
sourcePath: this.appData.sourcePath,
};
},
skip() {
return !this.appData.isSupportedContent;
},
error() {
createFlash(LOAD_CONTENT_ERROR);
},
},
},
computed: {
...mapState([
......@@ -44,7 +71,7 @@ export default {
...mapGetters(['contentChanged']),
},
mounted() {
if (this.isSupportedContent) {
if (this.appData.isSupportedContent) {
this.loadContent();
}
},
......@@ -66,7 +93,7 @@ export default {
/>
<!-- Main view -->
<template v-else-if="isSupportedContent">
<template v-else-if="appData.isSupportedContent">
<div v-if="isLoadingContent" class="w-50 h-50">
<gl-skeleton-loader :width="500" :height="102">
<rect width="500" height="16" rx="4" />
......
import createFlash from '~/flash';
import { __ } from '~/locale';
import * as mutationTypes from './mutation_types';
import loadSourceContent from '~/static_site_editor/services/load_source_content';
import submitContentChanges from '~/static_site_editor/services/submit_content_changes';
import { LOAD_CONTENT_ERROR } from '../constants';
export const loadContent = ({ commit, state: { sourcePath, projectId } }) => {
commit(mutationTypes.LOAD_CONTENT);
......@@ -12,7 +13,7 @@ export const loadContent = ({ commit, state: { sourcePath, projectId } }) => {
.then(data => commit(mutationTypes.RECEIVE_CONTENT_SUCCESS, data))
.catch(() => {
commit(mutationTypes.RECEIVE_CONTENT_ERROR);
createFlash(__('An error ocurred while loading your content. Please try again.'));
createFlash(LOAD_CONTENT_ERROR);
});
};
......
import fileResolver from '~/static_site_editor/graphql/resolvers/file';
import loadSourceContent from '~/static_site_editor/services/load_source_content';
import {
projectId,
sourcePath,
sourceContentTitle as title,
sourceContent as content,
} from '../../mock_data';
jest.mock('~/static_site_editor/services/load_source_content', () => jest.fn());
describe('static_site_editor/graphql/resolvers/file', () => {
it('returns file content and title when fetching file successfully', () => {
loadSourceContent.mockResolvedValueOnce({ title, content });
return fileResolver({ fullPath: projectId }, { path: sourcePath }).then(file => {
expect(file).toEqual({
__typename: 'File',
title,
content,
});
});
});
});
......@@ -66,7 +66,7 @@ describe('static_site_editor/pages/home', () => {
});
};
const buildWrapper = (data = { isSupportedContent: true }) => {
const buildWrapper = (data = { appData: { isSupportedContent: true } }) => {
wrapper = shallowMount(Home, {
localVue,
store,
......@@ -196,7 +196,7 @@ describe('static_site_editor/pages/home', () => {
});
it('displays invalid content message when content is not supported', () => {
buildWrapper({ isSupportedContent: false });
buildWrapper({ appData: { isSupportedContent: false } });
expect(findInvalidContentMessage().exists()).toBe(true);
});
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment