Feature/website overhaul (#49)
* Reorganize repo * Overhaul website design and rewrite in NextJS and Typescript * Delete website-publish.yml
This commit is contained in:
parent
3674ee5bd8
commit
421ecf17e6
32
.github/workflows/website-publish.yml
vendored
32
.github/workflows/website-publish.yml
vendored
@ -1,32 +0,0 @@
|
|||||||
name: Website Publish
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- website/**
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: '16'
|
|
||||||
cache: 'yarn'
|
|
||||||
cache-dependency-path: 'website/yarn.lock'
|
|
||||||
- name: Install
|
|
||||||
working-directory: website
|
|
||||||
run: yarn install --immutable
|
|
||||||
- name: Build
|
|
||||||
working-directory: website
|
|
||||||
run: yarn build
|
|
||||||
- name: Deploy
|
|
||||||
uses: peaceiris/actions-gh-pages@v3
|
|
||||||
with:
|
|
||||||
github_token: ${{ secrets.ACCESS_TOKEN }}
|
|
||||||
publish_dir: website/dist
|
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,6 +1,5 @@
|
|||||||
dist/
|
dist/
|
||||||
bin/
|
bin/
|
||||||
public/
|
|
||||||
node_modules/
|
node_modules/
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
.DS_Store
|
.DS_Store
|
||||||
@ -20,3 +19,4 @@ coverage/
|
|||||||
.env
|
.env
|
||||||
.temp/
|
.temp/
|
||||||
*.tgz
|
*.tgz
|
||||||
|
old-website
|
||||||
|
33
.stylelintrc
33
.stylelintrc
@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"processors": ["stylelint-processor-styled-components"],
|
|
||||||
"extends": ["stylelint-config-standard-scss", "stylelint-config-styled-components"],
|
|
||||||
"customSyntax": "postcss-scss",
|
|
||||||
"rules": {
|
|
||||||
"block-no-empty": null,
|
|
||||||
"no-duplicate-selectors": null,
|
|
||||||
"no-empty-source": null,
|
|
||||||
"no-extra-semicolons": null,
|
|
||||||
"declaration-empty-line-before": null,
|
|
||||||
"string-quotes": null,
|
|
||||||
"selector-class-pattern": null,
|
|
||||||
"selector-pseudo-element-colon-notation": null,
|
|
||||||
"rule-empty-line-before": null,
|
|
||||||
"declaration-colon-newline-after": null,
|
|
||||||
"at-rule-empty-line-before": null,
|
|
||||||
"alpha-value-notation": null,
|
|
||||||
"color-function-notation": null,
|
|
||||||
"keyframes-name-pattern": null,
|
|
||||||
"value-list-comma-newline-after": null,
|
|
||||||
"no-descending-specificity": null,
|
|
||||||
"selector-type-no-unknown": [
|
|
||||||
true,
|
|
||||||
{
|
|
||||||
"ignoreTypes": ["$dummyValue"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"value-keyword-case": [
|
|
||||||
"lower",
|
|
||||||
{ "ignoreKeywords": ["dummyValue"], "camelCaseSvgKeywords": true }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
StylesPath = website/src/writing-guide/styles
|
|
||||||
Vocab = website/src/writing-guide/vocab
|
|
||||||
MinAlertLevel = warning
|
|
||||||
|
|
||||||
[*.md]
|
|
||||||
BasedOnStyles = Avoid, Replace
|
|
87
README.md
87
README.md
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/StaticJsCMS/static-cms/blob/main/LICENSE)
|
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/StaticJsCMS/static-cms/blob/main/LICENSE)
|
||||||
[![npm latest package](https://img.shields.io/npm/v/@staticcms/core/latest.svg)](https://www.npmjs.com/package/@staticcms/core)
|
[![npm latest package](https://img.shields.io/npm/v/@staticcms/core/latest.svg)](https://www.npmjs.com/package/@staticcms/core)
|
||||||
|
[![npm next package](https://img.shields.io/npm/v/@staticcms/core/next.svg)](https://www.npmjs.com/package/@staticcms/core/v/next)
|
||||||
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/StaticJsCMS/static-cms/blob/main/CONTRIBUTING.md)
|
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/StaticJsCMS/static-cms/blob/main/CONTRIBUTING.md)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -13,6 +14,8 @@ A CMS for static site generators. Give users a simple way to edit
|
|||||||
and add content to any site built with a static site generator.
|
and add content to any site built with a static site generator.
|
||||||
|
|
||||||
> **DISCLAIMER**: This package/repository is under heavy development and as such is very unstable at current. A stable release is targeted for the end of Novemeber and will be labeled `1.0.0`. Documentation may not be completely accurate prior to the `1.0.0` release.
|
> **DISCLAIMER**: This package/repository is under heavy development and as such is very unstable at current. A stable release is targeted for the end of Novemeber and will be labeled `1.0.0`. Documentation may not be completely accurate prior to the `1.0.0` release.
|
||||||
|
>
|
||||||
|
> An alpha build for the stable release is available under the `@next` tack on npm.
|
||||||
|
|
||||||
## Community Chat
|
## Community Chat
|
||||||
|
|
||||||
@ -35,87 +38,9 @@ Read more about Static CMS [Core Concepts](https://staticjscms.github.io/static-
|
|||||||
The Static CMS can be used in two different ways.
|
The Static CMS can be used in two different ways.
|
||||||
|
|
||||||
* A Quick and easy install, that requires you to create a single HTML file and a configuration file. All the CMS JavaScript and CSS are loaded from a CDN.
|
* A Quick and easy install, that requires you to create a single HTML file and a configuration file. All the CMS JavaScript and CSS are loaded from a CDN.
|
||||||
To learn more about this installation method, refer to the [Quick Start Guide](https://staticjscms.github.io/static-cms/docs/start-with-a-template/)
|
To learn more about this installation method, refer to the [CDN Hosting Guide](https://staticjscms.github.io/static-cms/docs/add-to-your-site-cdn/)
|
||||||
* A complete, more complex install, that gives you more flexibility but requires that you use a static site builder with a build system that supports npm packages.
|
* A complete, more complex install, that gives you more flexibility but requires that you use a static site builder with a build system that supports npm packages.
|
||||||
|
To learn more about this installation method, refer to the [Bundling Guide](https://staticjscms.github.io/static-cms/docs/add-to-your-site-bundling/)
|
||||||
# static-cms-core
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
`npm install @staticcms/core`
|
|
||||||
|
|
||||||
## Setup
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import React from 'react';
|
|
||||||
import {
|
|
||||||
AzureBackend,
|
|
||||||
BitbucketBackend,
|
|
||||||
BooleanWidget,
|
|
||||||
CodeWidget,
|
|
||||||
ColorStringWidget,
|
|
||||||
DateTimeWidget,
|
|
||||||
FileWidget,
|
|
||||||
GitGatewayBackend,
|
|
||||||
GitHubBackend,
|
|
||||||
GitLabBackend,
|
|
||||||
imageEditorComponent,
|
|
||||||
ImageWidget,
|
|
||||||
ListWidget,
|
|
||||||
MapWidget,
|
|
||||||
MarkdownWidget,
|
|
||||||
StaticCmsCore as CMS,
|
|
||||||
NumberWidget,
|
|
||||||
ObjectWidget,
|
|
||||||
ProxyBackend,
|
|
||||||
RelationWidget,
|
|
||||||
SelectWidget,
|
|
||||||
StringWidget,
|
|
||||||
TestBackend,
|
|
||||||
TextWidget,
|
|
||||||
locales,
|
|
||||||
Icon,
|
|
||||||
images
|
|
||||||
} from '@static-cms/static-cms-core';
|
|
||||||
|
|
||||||
// Register all the things
|
|
||||||
CMS.registerBackend('git-gateway', GitGatewayBackend);
|
|
||||||
CMS.registerBackend('azure', AzureBackend);
|
|
||||||
CMS.registerBackend('github', GitHubBackend);
|
|
||||||
CMS.registerBackend('gitlab', GitLabBackend);
|
|
||||||
CMS.registerBackend('bitbucket', BitbucketBackend);
|
|
||||||
CMS.registerBackend('test-repo', TestBackend);
|
|
||||||
CMS.registerBackend('proxy', ProxyBackend);
|
|
||||||
CMS.registerWidget([
|
|
||||||
StringWidget.Widget(),
|
|
||||||
NumberWidget.Widget(),
|
|
||||||
TextWidget.Widget(),
|
|
||||||
ImageWidget.Widget(),
|
|
||||||
FileWidget.Widget(),
|
|
||||||
SelectWidget.Widget(),
|
|
||||||
MarkdownWidget.Widget(),
|
|
||||||
ListWidget.Widget(),
|
|
||||||
ObjectWidget.Widget(),
|
|
||||||
RelationWidget.Widget(),
|
|
||||||
BooleanWidget.Widget(),
|
|
||||||
MapWidget.Widget(),
|
|
||||||
DateTimeWidget.Widget(),
|
|
||||||
CodeWidget.Widget(),
|
|
||||||
ColorStringWidget.Widget(),
|
|
||||||
]);
|
|
||||||
CMS.registerEditorComponent(imageEditorComponent);
|
|
||||||
CMS.registerEditorComponent({
|
|
||||||
id: 'code-block',
|
|
||||||
label: 'Code Block',
|
|
||||||
widget: 'code',
|
|
||||||
type: 'code-block',
|
|
||||||
});
|
|
||||||
CMS.registerLocale('en', locales.en);
|
|
||||||
|
|
||||||
Object.keys(images).forEach(iconName => {
|
|
||||||
CMS.registerIcon(iconName, <Icon type={iconName} />);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
@ -133,6 +58,6 @@ Please make sure you understand its [implications and guarantees](https://writin
|
|||||||
|
|
||||||
# Netlify CMS
|
# Netlify CMS
|
||||||
|
|
||||||
Static CMS is a fork of Netlify CMS focusing on the core product over adding massive new features.
|
Static CMS is a fork of Netlify CMS focusing on the core product over adding massive, scope expanding, new features.
|
||||||
|
|
||||||
# Thanks
|
# Thanks
|
||||||
|
Before Width: | Height: | Size: 808 KiB After Width: | Height: | Size: 808 KiB |
Before Width: | Height: | Size: 310 KiB After Width: | Height: | Size: 310 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
@ -52,17 +52,13 @@
|
|||||||
"@emotion/styled": "11.10.4",
|
"@emotion/styled": "11.10.4",
|
||||||
"@iarna/toml": "2.2.5",
|
"@iarna/toml": "2.2.5",
|
||||||
"@mui/icons-material": "5.10.6",
|
"@mui/icons-material": "5.10.6",
|
||||||
"@mui/material": "5.10.6",
|
"@mui/material": "5.10.10",
|
||||||
"@mui/x-date-pickers": "5.0.4",
|
"@mui/x-date-pickers": "5.0.4",
|
||||||
"@reduxjs/toolkit": "1.8.5",
|
"@reduxjs/toolkit": "1.8.5",
|
||||||
"@toast-ui/react-editor": "3.2.2",
|
"@toast-ui/react-editor": "3.2.2",
|
||||||
"ajv": "8.11.0",
|
"ajv": "8.11.0",
|
||||||
"ajv-errors": "3.0.0",
|
"ajv-errors": "3.0.0",
|
||||||
"ajv-keywords": "5.1.0",
|
"ajv-keywords": "5.1.0",
|
||||||
"apollo-cache-inmemory": "1.6.6",
|
|
||||||
"apollo-client": "2.6.10",
|
|
||||||
"apollo-link-context": "1.0.20",
|
|
||||||
"apollo-link-http": "1.5.17",
|
|
||||||
"array-move": "4.0.0",
|
"array-move": "4.0.0",
|
||||||
"buffer": "6.0.3",
|
"buffer": "6.0.3",
|
||||||
"clean-stack": "4.2.0",
|
"clean-stack": "4.2.0",
|
@ -19,7 +19,6 @@ import {
|
|||||||
} from '../../lib/util';
|
} from '../../lib/util';
|
||||||
import API, { API_NAME } from './API';
|
import API, { API_NAME } from './API';
|
||||||
import AuthenticationPage from './AuthenticationPage';
|
import AuthenticationPage from './AuthenticationPage';
|
||||||
import GraphQLAPI from './GraphQLAPI';
|
|
||||||
|
|
||||||
import type { Octokit } from '@octokit/rest';
|
import type { Octokit } from '@octokit/rest';
|
||||||
import type { Semaphore } from 'semaphore';
|
import type { Semaphore } from 'semaphore';
|
||||||
@ -66,7 +65,6 @@ export default class GitHub implements BackendClass {
|
|||||||
apiRoot: string;
|
apiRoot: string;
|
||||||
mediaFolder?: string;
|
mediaFolder?: string;
|
||||||
token: string | null;
|
token: string | null;
|
||||||
useGraphql: boolean;
|
|
||||||
_currentUserPromise?: Promise<GitHubUser>;
|
_currentUserPromise?: Promise<GitHubUser>;
|
||||||
_userIsOriginMaintainerPromises?: {
|
_userIsOriginMaintainerPromises?: {
|
||||||
[key: string]: Promise<boolean>;
|
[key: string]: Promise<boolean>;
|
||||||
@ -92,7 +90,6 @@ export default class GitHub implements BackendClass {
|
|||||||
this.branch = config.backend.branch?.trim() || 'main';
|
this.branch = config.backend.branch?.trim() || 'main';
|
||||||
this.apiRoot = config.backend.api_root || 'https://api.github.com';
|
this.apiRoot = config.backend.api_root || 'https://api.github.com';
|
||||||
this.token = '';
|
this.token = '';
|
||||||
this.useGraphql = config.backend.use_graphql || false;
|
|
||||||
this.mediaFolder = config.media_folder;
|
this.mediaFolder = config.media_folder;
|
||||||
this.lock = asyncLock();
|
this.lock = asyncLock();
|
||||||
}
|
}
|
||||||
@ -179,7 +176,7 @@ export default class GitHub implements BackendClass {
|
|||||||
|
|
||||||
async authenticate(state: Credentials) {
|
async authenticate(state: Credentials) {
|
||||||
this.token = state.token as string;
|
this.token = state.token as string;
|
||||||
const apiCtor = this.useGraphql ? GraphQLAPI : API;
|
const apiCtor = API;
|
||||||
this.api = new apiCtor({
|
this.api = new apiCtor({
|
||||||
token: this.token,
|
token: this.token,
|
||||||
branch: this.branch,
|
branch: this.branch,
|
@ -1,7 +1,3 @@
|
|||||||
import { InMemoryCache } from 'apollo-cache-inmemory';
|
|
||||||
import { ApolloClient } from 'apollo-client';
|
|
||||||
import { setContext } from 'apollo-link-context';
|
|
||||||
import { createHttpLink } from 'apollo-link-http';
|
|
||||||
import { Base64 } from 'js-base64';
|
import { Base64 } from 'js-base64';
|
||||||
import partial from 'lodash/partial';
|
import partial from 'lodash/partial';
|
||||||
import result from 'lodash/result';
|
import result from 'lodash/result';
|
||||||
@ -20,25 +16,18 @@ import {
|
|||||||
throwOnConflictingBranches,
|
throwOnConflictingBranches,
|
||||||
unsentRequest,
|
unsentRequest,
|
||||||
} from '../../lib/util';
|
} from '../../lib/util';
|
||||||
import * as queries from './queries';
|
|
||||||
|
|
||||||
import type { NormalizedCacheObject } from 'apollo-cache-inmemory';
|
import type { DataFile, PersistOptions } from '../../interface';
|
||||||
import type { ApolloQueryResult } from 'apollo-client';
|
|
||||||
import type { DataFile, ImplementationFile, PersistOptions } from '../../interface';
|
|
||||||
import type { ApiRequest, FetchError } from '../../lib/util';
|
import type { ApiRequest, FetchError } from '../../lib/util';
|
||||||
import type AssetProxy from '../../valueObjects/AssetProxy';
|
import type AssetProxy from '../../valueObjects/AssetProxy';
|
||||||
|
|
||||||
export const API_NAME = 'GitLab';
|
export const API_NAME = 'GitLab';
|
||||||
|
|
||||||
const NO_CACHE = 'no-cache';
|
|
||||||
|
|
||||||
export interface Config {
|
export interface Config {
|
||||||
apiRoot?: string;
|
apiRoot?: string;
|
||||||
graphQLAPIRoot?: string;
|
|
||||||
token?: string;
|
token?: string;
|
||||||
branch?: string;
|
branch?: string;
|
||||||
repo?: string;
|
repo?: string;
|
||||||
useGraphQL?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CommitAuthor {
|
export interface CommitAuthor {
|
||||||
@ -130,65 +119,20 @@ export function getMaxAccess(groups: { group_access_level: number }[]) {
|
|||||||
}, groups[0]);
|
}, groups[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function batch<T>(items: T[], maxPerBatch: number, action: (items: T[]) => void) {
|
|
||||||
for (let index = 0; index < items.length; index = index + maxPerBatch) {
|
|
||||||
const itemsSlice = items.slice(index, index + maxPerBatch);
|
|
||||||
action(itemsSlice);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class API {
|
export default class API {
|
||||||
apiRoot: string;
|
apiRoot: string;
|
||||||
graphQLAPIRoot: string;
|
|
||||||
token: string | boolean;
|
token: string | boolean;
|
||||||
branch: string;
|
branch: string;
|
||||||
repo: string;
|
repo: string;
|
||||||
repoURL: string;
|
repoURL: string;
|
||||||
commitAuthor?: CommitAuthor;
|
commitAuthor?: CommitAuthor;
|
||||||
|
|
||||||
graphQLClient?: ApolloClient<NormalizedCacheObject>;
|
|
||||||
|
|
||||||
constructor(config: Config) {
|
constructor(config: Config) {
|
||||||
this.apiRoot = config.apiRoot || 'https://gitlab.com/api/v4';
|
this.apiRoot = config.apiRoot || 'https://gitlab.com/api/v4';
|
||||||
this.graphQLAPIRoot = config.graphQLAPIRoot || 'https://gitlab.com/api/graphql';
|
|
||||||
this.token = config.token || false;
|
this.token = config.token || false;
|
||||||
this.branch = config.branch || 'main';
|
this.branch = config.branch || 'main';
|
||||||
this.repo = config.repo || '';
|
this.repo = config.repo || '';
|
||||||
this.repoURL = `/projects/${encodeURIComponent(this.repo)}`;
|
this.repoURL = `/projects/${encodeURIComponent(this.repo)}`;
|
||||||
if (config.useGraphQL === true) {
|
|
||||||
this.graphQLClient = this.getApolloClient();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getApolloClient() {
|
|
||||||
const authLink = setContext((_, { headers }) => {
|
|
||||||
return {
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json; charset=utf-8',
|
|
||||||
...headers,
|
|
||||||
authorization: this.token ? `token ${this.token}` : '',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
const httpLink = createHttpLink({ uri: this.graphQLAPIRoot });
|
|
||||||
return new ApolloClient({
|
|
||||||
link: authLink.concat(httpLink),
|
|
||||||
cache: new InMemoryCache(),
|
|
||||||
defaultOptions: {
|
|
||||||
watchQuery: {
|
|
||||||
fetchPolicy: NO_CACHE,
|
|
||||||
errorPolicy: 'ignore',
|
|
||||||
},
|
|
||||||
query: {
|
|
||||||
fetchPolicy: NO_CACHE,
|
|
||||||
errorPolicy: 'all',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
reset() {
|
|
||||||
return this.graphQLClient?.resetStore();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
withAuthorizationHeaders = (req: ApiRequest) => {
|
withAuthorizationHeaders = (req: ApiRequest) => {
|
||||||
@ -374,102 +318,7 @@ export default class API {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
listAllFilesGraphQL = async (path: string, recursive: boolean, branch: String) => {
|
|
||||||
const files: FileEntry[] = [];
|
|
||||||
let blobsPaths;
|
|
||||||
let cursor;
|
|
||||||
do {
|
|
||||||
blobsPaths = await this.graphQLClient!.query({
|
|
||||||
query: queries.files,
|
|
||||||
variables: { repo: this.repo, branch, path, recursive, cursor },
|
|
||||||
});
|
|
||||||
files.push(...blobsPaths.data.project.repository.tree.blobs.nodes);
|
|
||||||
cursor = blobsPaths.data.project.repository.tree.blobs.pageInfo.endCursor;
|
|
||||||
} while (blobsPaths.data.project.repository.tree.blobs.pageInfo.hasNextPage);
|
|
||||||
|
|
||||||
return files;
|
|
||||||
};
|
|
||||||
|
|
||||||
readFilesGraphQL = async (files: ImplementationFile[]) => {
|
|
||||||
const paths = files.map(({ path }) => path);
|
|
||||||
|
|
||||||
type BlobResult = {
|
|
||||||
project: { repository: { blobs: { nodes: { id: string; data: string }[] } } };
|
|
||||||
};
|
|
||||||
|
|
||||||
const blobPromises: Promise<ApolloQueryResult<BlobResult>>[] = [];
|
|
||||||
batch(paths, 90, slice => {
|
|
||||||
blobPromises.push(
|
|
||||||
this.graphQLClient!.query({
|
|
||||||
query: queries.blobs,
|
|
||||||
variables: {
|
|
||||||
repo: this.repo,
|
|
||||||
branch: this.branch,
|
|
||||||
paths: slice,
|
|
||||||
},
|
|
||||||
fetchPolicy: 'cache-first',
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
type LastCommit = {
|
|
||||||
id: string;
|
|
||||||
authoredDate: string;
|
|
||||||
authorName: string;
|
|
||||||
author?: {
|
|
||||||
name: string;
|
|
||||||
username: string;
|
|
||||||
publicEmail: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
type CommitResult = {
|
|
||||||
project: { repository: { [tree: string]: { lastCommit: LastCommit } } };
|
|
||||||
};
|
|
||||||
|
|
||||||
const commitPromises: Promise<ApolloQueryResult<CommitResult>>[] = [];
|
|
||||||
batch(paths, 8, slice => {
|
|
||||||
commitPromises.push(
|
|
||||||
this.graphQLClient!.query({
|
|
||||||
query: queries.lastCommits(slice),
|
|
||||||
variables: {
|
|
||||||
repo: this.repo,
|
|
||||||
branch: this.branch,
|
|
||||||
},
|
|
||||||
fetchPolicy: 'cache-first',
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const [blobsResults, commitsResults] = await Promise.all([
|
|
||||||
(await Promise.all(blobPromises)).map(result => result.data.project.repository.blobs.nodes),
|
|
||||||
(
|
|
||||||
await Promise.all(commitPromises)
|
|
||||||
).map(
|
|
||||||
result =>
|
|
||||||
Object.values(result.data.project.repository)
|
|
||||||
.map(({ lastCommit }) => lastCommit)
|
|
||||||
.filter(Boolean) as LastCommit[],
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const blobs = blobsResults.flat().map(result => result.data) as string[];
|
|
||||||
const metadata = commitsResults.flat().map(({ author, authoredDate, authorName }) => ({
|
|
||||||
author: author ? author.name || author.username || author.publicEmail : authorName,
|
|
||||||
updatedOn: authoredDate,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const filesWithData = files.map((file, index) => ({
|
|
||||||
file: { ...file, ...metadata[index] },
|
|
||||||
data: blobs[index],
|
|
||||||
}));
|
|
||||||
return filesWithData;
|
|
||||||
};
|
|
||||||
|
|
||||||
listAllFiles = async (path: string, recursive = false, branch = this.branch) => {
|
listAllFiles = async (path: string, recursive = false, branch = this.branch) => {
|
||||||
if (this.graphQLClient) {
|
|
||||||
return await this.listAllFilesGraphQL(path, recursive, branch);
|
|
||||||
}
|
|
||||||
const entries = [];
|
const entries = [];
|
||||||
// eslint-disable-next-line prefer-const
|
// eslint-disable-next-line prefer-const
|
||||||
let { cursor, entries: initialEntries } = await this.fetchCursorAndEntries({
|
let { cursor, entries: initialEntries } = await this.fetchCursorAndEntries({
|
@ -3,7 +3,7 @@ import React, { useCallback, useMemo, useState } from 'react';
|
|||||||
|
|
||||||
import AuthenticationPage from '../../components/UI/AuthenticationPage';
|
import AuthenticationPage from '../../components/UI/AuthenticationPage';
|
||||||
import Icon from '../../components/UI/Icon';
|
import Icon from '../../components/UI/Icon';
|
||||||
import { ImplicitAuthenticator, NetlifyAuthenticator, PkceAuthenticator } from '../../lib/auth';
|
import { NetlifyAuthenticator, PkceAuthenticator } from '../../lib/auth';
|
||||||
import { isNotEmpty } from '../../lib/util/string.util';
|
import { isNotEmpty } from '../../lib/util/string.util';
|
||||||
|
|
||||||
import type { MouseEvent } from 'react';
|
import type { MouseEvent } from 'react';
|
||||||
@ -19,7 +19,6 @@ const LoginButtonIcon = styled(Icon)`
|
|||||||
|
|
||||||
const clientSideAuthenticators = {
|
const clientSideAuthenticators = {
|
||||||
pkce: (config: AuthenticatorConfig) => new PkceAuthenticator(config),
|
pkce: (config: AuthenticatorConfig) => new PkceAuthenticator(config),
|
||||||
implicit: (config: AuthenticatorConfig) => new ImplicitAuthenticator(config),
|
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const GitLabAuthenticationPage = ({
|
const GitLabAuthenticationPage = ({
|
@ -49,8 +49,6 @@ export default class GitLab implements BackendClass {
|
|||||||
apiRoot: string;
|
apiRoot: string;
|
||||||
token: string | null;
|
token: string | null;
|
||||||
mediaFolder?: string;
|
mediaFolder?: string;
|
||||||
useGraphQL: boolean;
|
|
||||||
graphQLAPIRoot: string;
|
|
||||||
|
|
||||||
_mediaDisplayURLSem?: Semaphore;
|
_mediaDisplayURLSem?: Semaphore;
|
||||||
|
|
||||||
@ -75,8 +73,6 @@ export default class GitLab implements BackendClass {
|
|||||||
this.apiRoot = config.backend.api_root || 'https://gitlab.com/api/v4';
|
this.apiRoot = config.backend.api_root || 'https://gitlab.com/api/v4';
|
||||||
this.token = '';
|
this.token = '';
|
||||||
this.mediaFolder = config.media_folder;
|
this.mediaFolder = config.media_folder;
|
||||||
this.useGraphQL = config.backend.use_graphql || false;
|
|
||||||
this.graphQLAPIRoot = config.backend.graphql_api_root || 'https://gitlab.com/api/graphql';
|
|
||||||
this.lock = asyncLock();
|
this.lock = asyncLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,8 +108,6 @@ export default class GitLab implements BackendClass {
|
|||||||
branch: this.branch,
|
branch: this.branch,
|
||||||
repo: this.repo,
|
repo: this.repo,
|
||||||
apiRoot: this.apiRoot,
|
apiRoot: this.apiRoot,
|
||||||
useGraphQL: this.useGraphQL,
|
|
||||||
graphQLAPIRoot: this.graphQLAPIRoot,
|
|
||||||
});
|
});
|
||||||
const user = await this.api.user();
|
const user = await this.api.user();
|
||||||
const isCollab = await this.api.hasWriteAccess().catch((error: Error) => {
|
const isCollab = await this.api.hasWriteAccess().catch((error: Error) => {
|
||||||
@ -200,7 +194,7 @@ export default class GitLab implements BackendClass {
|
|||||||
getDifferences: (to, from) => this.api!.getDifferences(to, from),
|
getDifferences: (to, from) => this.api!.getDifferences(to, from),
|
||||||
getFileId: path => this.api!.getFileId(path, this.branch),
|
getFileId: path => this.api!.getFileId(path, this.branch),
|
||||||
filterFile: file => this.filterFile(folder, file, extension, depth),
|
filterFile: file => this.filterFile(folder, file, extension, depth),
|
||||||
customFetch: this.useGraphQL ? files => this.api!.readFilesGraphQL(files) : undefined,
|
customFetch: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
return files;
|
return files;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user