diff --git a/src/lib/api/interface/Api.ts b/src/lib/api/interface/Api.ts index 48284f5..1a55c71 100644 --- a/src/lib/api/interface/Api.ts +++ b/src/lib/api/interface/Api.ts @@ -11,7 +11,6 @@ import { cache } from ".."; - export interface LoginConfig { /** * RBAC will remain enabled on GUI if "external". That only works @@ -63,6 +62,48 @@ export interface SetupState { }; } +export interface AkskList { + pagination: { + /** Next page is available */ + has_more: boolean; + /** Token used to retrieve the next page */ + next_offset: string; + /** + * Number of values found in the results + * @min 0 + */ + results: number; + /** + * Maximal number of entries per page + * @min 0 + */ + max_per_page: number; + }; + results: { + /** @format uuid */ + id: string; + access_key: string; + secret_key: string; + description?: string; + /** @format int64 */ + created_at: number; + /** @format int64 */ + updated_at: number; + }[]; +} + +export interface Aksk { + /** @format uuid */ + id: string; + access_key: string; + secret_key: string; + description?: string; + /** @format int64 */ + created_at: number; + /** @format int64 */ + updated_at: number; +} + export interface BranchCreation { name: string; source: string; @@ -695,171 +736,171 @@ export enum ContentType { Text = "text/plain", } export class HttpClient { - public baseUrl: string = window.JIAOZIFS_API_URL; - private securityData: SecurityDataType | null = null; - private securityWorker?: ApiConfig["securityWorker"]; - private abortControllers = new Map(); - private customFetch = (...fetchParams: Parameters) => fetch(...fetchParams); - - private baseApiParams: RequestParams = { - credentials: "same-origin", - headers: {}, - redirect: "follow", - referrerPolicy: "no-referrer", - }; - - constructor(apiConfig: ApiConfig = {}) { - Object.assign(this, apiConfig); - } - - public setSecurityData = (data: SecurityDataType | null) => { - this.securityData = data; + public baseUrl: string = window.JIAOZIFS_API_URL; + private securityData: SecurityDataType | null = null; + private securityWorker?: ApiConfig["securityWorker"]; + private abortControllers = new Map(); + private customFetch = (...fetchParams: Parameters) => fetch(...fetchParams); + + private baseApiParams: RequestParams = { + credentials: "same-origin", + headers: {}, + redirect: "follow", + referrerPolicy: "no-referrer", + }; + + constructor(apiConfig: ApiConfig = {}) { + Object.assign(this, apiConfig); + } + + public setSecurityData = (data: SecurityDataType | null) => { + this.securityData = data; + }; + + protected encodeQueryParam(key: string, value: any) { + const encodedKey = encodeURIComponent(key); + return `${encodedKey}=${encodeURIComponent(typeof value === "number" ? value : `${value}`)}`; + } + + protected addQueryParam(query: QueryParamsType, key: string) { + return this.encodeQueryParam(key, query[key]); + } + + protected addArrayQueryParam(query: QueryParamsType, key: string) { + const value = query[key]; + return value.map((v: any) => this.encodeQueryParam(key, v)).join("&"); + } + + protected toQueryString(rawQuery?: QueryParamsType): string { + const query = rawQuery || {}; + const keys = Object.keys(query).filter((key) => "undefined" !== typeof query[key]); + return keys + .map((key) => (Array.isArray(query[key]) ? this.addArrayQueryParam(query, key) : this.addQueryParam(query, key))) + .join("&"); + } + + protected addQueryParams(rawQuery?: QueryParamsType): string { + const queryString = this.toQueryString(rawQuery); + return queryString ? `?${queryString}` : ""; + } + + private contentFormatters: Record any> = { + [ContentType.Json]: (input: any) => + input !== null && (typeof input === "object" || typeof input === "string") ? JSON.stringify(input) : input, + [ContentType.Text]: (input: any) => (input !== null && typeof input !== "string" ? JSON.stringify(input) : input), + [ContentType.FormData]: (input: any) => + Object.keys(input || {}).reduce((formData, key) => { + const property = input[key]; + formData.append( + key, + property instanceof Blob + ? property + : typeof property === "object" && property !== null + ? JSON.stringify(property) + : `${property}`, + ); + return formData; + }, new FormData()), + [ContentType.UrlEncoded]: (input: any) => this.toQueryString(input), + }; + + protected mergeRequestParams(params1: RequestParams, params2?: RequestParams): RequestParams { + return { + ...this.baseApiParams, + ...params1, + ...(params2 || {}), + headers: { + ...(this.baseApiParams.headers || {}), + ...(params1.headers || {}), + ...((params2 && params2.headers) || {}), + }, }; - - protected encodeQueryParam(key: string, value: any) { - const encodedKey = encodeURIComponent(key); - return `${encodedKey}=${encodeURIComponent(typeof value === "number" ? value : `${value}`)}`; - } - - protected addQueryParam(query: QueryParamsType, key: string) { - return this.encodeQueryParam(key, query[key]); - } - - protected addArrayQueryParam(query: QueryParamsType, key: string) { - const value = query[key]; - return value.map((v: any) => this.encodeQueryParam(key, v)).join("&"); - } - - protected toQueryString(rawQuery?: QueryParamsType): string { - const query = rawQuery || {}; - const keys = Object.keys(query).filter((key) => "undefined" !== typeof query[key]); - return keys - .map((key) => (Array.isArray(query[key]) ? this.addArrayQueryParam(query, key) : this.addQueryParam(query, key))) - .join("&"); + } + + protected createAbortSignal = (cancelToken: CancelToken): AbortSignal | undefined => { + if (this.abortControllers.has(cancelToken)) { + const abortController = this.abortControllers.get(cancelToken); + if (abortController) { + return abortController.signal; + } + return void 0; } - - protected addQueryParams(rawQuery?: QueryParamsType): string { - const queryString = this.toQueryString(rawQuery); - return queryString ? `?${queryString}` : ""; + + const abortController = new AbortController(); + this.abortControllers.set(cancelToken, abortController); + return abortController.signal; + }; + + public abortRequest = (cancelToken: CancelToken) => { + const abortController = this.abortControllers.get(cancelToken); + + if (abortController) { + abortController.abort(); + this.abortControllers.delete(cancelToken); } - - private contentFormatters: Record any> = { - [ContentType.Json]: (input: any) => - input !== null && (typeof input === "object" || typeof input === "string") ? JSON.stringify(input) : input, - [ContentType.Text]: (input: any) => (input !== null && typeof input !== "string" ? JSON.stringify(input) : input), - [ContentType.FormData]: (input: any) => - Object.keys(input || {}).reduce((formData, key) => { - const property = input[key]; - formData.append( - key, - property instanceof Blob - ? property - : typeof property === "object" && property !== null - ? JSON.stringify(property) - : `${property}`, - ); - return formData; - }, new FormData()), - [ContentType.UrlEncoded]: (input: any) => this.toQueryString(input), - }; - - protected mergeRequestParams(params1: RequestParams, params2?: RequestParams): RequestParams { - return { - ...this.baseApiParams, - ...params1, - ...(params2 || {}), - headers: { - ...(this.baseApiParams.headers || {}), - ...(params1.headers || {}), - ...((params2 && params2.headers) || {}), - }, - }; + }; + + public request = async ({ + body, + secure, + path, + type, + query, + format, + baseUrl, + cancelToken, + ...params + }: FullRequestParams): Promise> => { + const secureParams = + ((typeof secure === "boolean" ? secure : this.baseApiParams.secure) && + this.securityWorker && + (await this.securityWorker(this.securityData))) || + {}; + const requestParams = this.mergeRequestParams(params, secureParams); + const queryString = query && this.toQueryString(query); + const payloadFormatter = this.contentFormatters[type || ContentType.Json]; + const responseFormat = format || requestParams.format; + const token = cache.get('token'); + let headers = { + ...(requestParams.headers || {}), + ...(type && type !== ContentType.FormData ? { "Content-Type": type } : {}), + ...(token?{'Authorization': `Bearer ${token}`}:{}) } - - protected createAbortSignal = (cancelToken: CancelToken): AbortSignal | undefined => { - if (this.abortControllers.has(cancelToken)) { - const abortController = this.abortControllers.get(cancelToken); - if (abortController) { - return abortController.signal; - } - return void 0; - } - - const abortController = new AbortController(); - this.abortControllers.set(cancelToken, abortController); - return abortController.signal; - }; - - public abortRequest = (cancelToken: CancelToken) => { - const abortController = this.abortControllers.get(cancelToken); - - if (abortController) { - abortController.abort(); + return this.customFetch(`${baseUrl || this.baseUrl || ""}${path}${queryString ? `?${queryString}` : ""}`, { + ...requestParams, + headers: headers, + signal: (cancelToken ? this.createAbortSignal(cancelToken) : requestParams.signal) || null, + body: typeof body === "undefined" || body === null ? null : payloadFormatter(body), + }).then(async (response) => { + const r = response as HttpResponse; + r.data = null as unknown as T; + r.error = null as unknown as E; + + const data = !responseFormat + ? r + : await response[responseFormat]() + .then((data) => { + if (r.ok) { + r.data = data; + } else { + r.error = data; + } + return r; + }) + .catch((e) => { + r.error = e; + return r; + }); + + if (cancelToken) { this.abortControllers.delete(cancelToken); } - }; - - public request = async ({ - body, - secure, - path, - type, - query, - format, - baseUrl, - cancelToken, - ...params - }: FullRequestParams): Promise> => { - const secureParams = - ((typeof secure === "boolean" ? secure : this.baseApiParams.secure) && - this.securityWorker && - (await this.securityWorker(this.securityData))) || - {}; - const requestParams = this.mergeRequestParams(params, secureParams); - const queryString = query && this.toQueryString(query); - const payloadFormatter = this.contentFormatters[type || ContentType.Json]; - const responseFormat = format || requestParams.format; - const token = cache.get('token'); - let headers = { - ...(requestParams.headers || {}), - ...(type && type !== ContentType.FormData ? { "Content-Type": type } : {}), - ...(token?{'Authorization': `Bearer ${token}`}:{}) - } - return this.customFetch(`${baseUrl || this.baseUrl || ""}${path}${queryString ? `?${queryString}` : ""}`, { - ...requestParams, - headers: headers, - signal: (cancelToken ? this.createAbortSignal(cancelToken) : requestParams.signal) || null, - body: typeof body === "undefined" || body === null ? null : payloadFormatter(body), - }).then(async (response) => { - const r = response as HttpResponse; - r.data = null as unknown as T; - r.error = null as unknown as E; - - const data = !responseFormat - ? r - : await response[responseFormat]() - .then((data) => { - if (r.ok) { - r.data = data; - } else { - r.error = data; - } - return r; - }) - .catch((e) => { - r.error = e; - return r; - }); - - if (cancelToken) { - this.abortControllers.delete(cancelToken); - } - - if (!response.ok) throw data; - return data; - }); - }; - } + + if (!response.ok) throw data; + return data; + }); + }; +} /** * @title jiaozifs API * @version 1.0.0 @@ -1575,10 +1616,18 @@ export class Api extends HttpClient + deleteRepository: ( + owner: string, + repository: string, + query?: { + is_clean_data?: boolean; + }, + params: RequestParams = {}, + ) => this.request({ path: `/repos/${owner}/${repository}`, method: "DELETE", + query: query, secure: true, ...params, }), @@ -2263,7 +2312,7 @@ export class Api extends HttpClient({ path: `/users/repos`, @@ -2368,6 +2417,173 @@ export class Api extends HttpClient + this.request< + { + /** @format uuid */ + id: string; + access_key: string; + secret_key: string; + description?: string; + /** @format int64 */ + created_at: number; + /** @format int64 */ + updated_at: number; + }, + void + >({ + path: `/users/aksk`, + method: "GET", + query: query, + secure: true, + format: "json", + ...params, + }), + + /** + * No description + * + * @tags aksks + * @name CreateAksk + * @summary create aksk + * @request POST:/users/aksk + * @secure + */ + createAksk: ( + query?: { + description?: string; + }, + params: RequestParams = {}, + ) => + this.request< + { + /** @format uuid */ + id: string; + access_key: string; + secret_key: string; + description?: string; + /** @format int64 */ + created_at: number; + /** @format int64 */ + updated_at: number; + }, + void + >({ + path: `/users/aksk`, + method: "POST", + query: query, + secure: true, + format: "json", + ...params, + }), + + /** + * No description + * + * @tags aksks + * @name DeleteAksk + * @summary delete aksk + * @request DELETE:/users/aksk + * @secure + */ + deleteAksk: ( + query?: { + /** @format uuid */ + id?: string; + access_key?: string; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/users/aksk`, + method: "DELETE", + query: query, + secure: true, + ...params, + }), + + /** + * No description + * + * @tags aksks + * @name ListAksks + * @summary list aksks + * @request GET:/users/aksks + * @secure + */ + listAksks: ( + query?: { + /** + * return items after this value + * @format int64 + */ + after?: number; + /** + * how many items to return + * @min -1 + * @max 1000 + * @default 100 + */ + amount?: number; + }, + params: RequestParams = {}, + ) => + this.request< + { + pagination: { + /** Next page is available */ + has_more: boolean; + /** Token used to retrieve the next page */ + next_offset: string; + /** + * Number of values found in the results + * @min 0 + */ + results: number; + /** + * Maximal number of entries per page + * @min 0 + */ + max_per_page: number; + }; + results: { + /** @format uuid */ + id: string; + access_key: string; + secret_key: string; + description?: string; + /** @format int64 */ + created_at: number; + /** @format int64 */ + updated_at: number; + }[]; + }, + void + >({ + path: `/users/aksks`, + method: "GET", + query: query, + secure: true, + format: "json", + ...params, + }), }; auth = { /** @@ -2423,13 +2639,3 @@ export class Api extends HttpClient { if (!bytes) return "0.0 B"; @@ -315,7 +316,7 @@ export const EntryRow = ({ repo, reference, path, entry, onDelete, showActions } } let size; - if (entry.diff_type === "removed" || entry.path_type === "common_prefix") { + if (entry.action === 2) { size = ; } else { size = ( @@ -329,7 +330,7 @@ export const EntryRow = ({ repo, reference, path, entry, onDelete, showActions } } let modified; - if (entry.diff_type === "removed" || entry.path_type === "common_prefix") { + if (entry.action ===2) { modified = ; } else { modified = ( @@ -347,8 +348,10 @@ export const EntryRow = ({ repo, reference, path, entry, onDelete, showActions } } let diffIndicator; - switch (entry.diff_type) { - case "removed": + let diffstyle; + switch (entry.action) { + case 2: + diffstyle = "diif-remove" diffIndicator = ( ); break; - case "added": + case 1: + diffstyle = "diif-add" diffIndicator = ( ); break; - case "changed": + case 3: + diffstyle = "diif-change" diffIndicator = ( - - {diffIndicator} - - {entry.is_dir === true ? ( - - ) : ( - - )}{" "} - {button} - - {entry.is_dir?'Directory':size} - {modified} - {entryActions} - - - ); + + {diffIndicator} + + {entry.is_dir === true ? ( + + ) : ( + + )}{" "} + {button} + + {entry.is_dir?'Directory':size} + {modified} + {entryActions} + + +); }; function pathParts(path, isPathToFile) { @@ -613,6 +619,7 @@ const GetStarted = ({ onUpload, onImport }) => { export const Tree = ({ repo, reference, + changes, results, after, onPaginate, @@ -624,7 +631,7 @@ export const Tree = ({ path = "", }) => { let body; - + if(results && changes) getActions(changes,results) if (results.length === 0 && path === "" && reference.type === RefTypeBranch) { // empty state! body = ( diff --git a/src/lib/components/repository/refDropdown.tsx b/src/lib/components/repository/refDropdown.tsx index 9af0ad8..0de3146 100644 --- a/src/lib/components/repository/refDropdown.tsx +++ b/src/lib/components/repository/refDropdown.tsx @@ -5,7 +5,7 @@ import {Nav, Badge,Form,Button,Alert,Overlay,Popover } from "react-bootstrap"; import {RefTypeBranch, RefTypeCommit, RefTypeTag} from "../../../constants"; import { CommitListProps, RefDropdownProps, RefEntryProps, RefSelectorProps, ref, RepoPaginatorProps, ResponseProps } from "../interface/comp_interface"; import { Commit } from "../../../pages/repositories/interface/repo_interface"; -import { repos } from "../../api/interface/Api"; +import { repos } from "../../api/interface"; const RefSelector:React.FC = ({ repo, selected, selectRef, withWorkspace, withTags, amount = 300 }) => { diff --git a/src/lib/hooks/conf.tsx b/src/lib/hooks/conf.tsx index b0db5d3..1c4b3e1 100644 --- a/src/lib/hooks/conf.tsx +++ b/src/lib/hooks/conf.tsx @@ -2,7 +2,7 @@ import React, {createContext, useContext, useMemo} from "react"; import {useAPI} from "./api"; import { LoginConfigProviderProps } from "../components/interface/comp_interface"; -import { setup } from "../api/interface/Api"; +import { setup } from "../api/interface"; export const LoginConfigContext = createContext({}); diff --git a/src/lib/hooks/repo.tsx b/src/lib/hooks/repo.tsx index aad3e52..2ea4e3c 100644 --- a/src/lib/hooks/repo.tsx +++ b/src/lib/hooks/repo.tsx @@ -3,7 +3,7 @@ import React, {useContext, useState, createContext, useEffect} from "react"; import { NotFoundError, BadRequestError, cache} from "../api"; import {useRouter} from "./router"; import {RefTypeBranch} from "../../constants"; -import { repos } from "../api/interface/Api"; +import { repos } from "../api/interface"; export const resolveRef = async (user,repoId:string, refId:string) => { diff --git a/src/pages/repositories/repository/repo-comp/changes/changes.tsx b/src/pages/repositories/repository/repo-comp/changes/changes.tsx index f62aead..4b2a6d9 100644 --- a/src/pages/repositories/repository/repo-comp/changes/changes.tsx +++ b/src/pages/repositories/repository/repo-comp/changes/changes.tsx @@ -23,6 +23,7 @@ import { ChangesBrowserProps, CommitButtonProps, Pair, ResultsState, RevertButto import { object, repos, wip } from "../../../../../lib/api/interface/index"; import { UploadButton } from "../objects/uplodaButton"; import ChangeList from "../../commits/commit/changesrow"; +import { getActions } from "../../../../../util/changes"; const CommitButton: React.FC = ({repo, onCommit, enabled = false}) => { @@ -158,9 +159,6 @@ const ChangesBrowser: React.FC = ({repo, reference, prefix, done: false, }; const [deleteState, setDeleteState] = useState(initialState); - // const getMoreUncommittedChanges:GetMoreUncommittedChanges = (afterUpdated, path, useDelimiter= true, amount = -1) => { - // return wip.getWipChanges(user,repo.name,{refName:reference.name}) - // } const {loading:loaded} = useAPI(()=>wip.getWip(repo.name,user,{refName:reference.name})) const { response,loading:load} = useAPI(async() => {return await repos.getEntriesInRef(user,repo.name,{ref:reference.name,type:'wip',path:path?path:'/'})} @@ -192,28 +190,7 @@ const ChangesBrowser: React.FC = ({repo, reference, prefix, }) } - // let onNavigate = (entry: { path: string; }) => { - // return { - // pathname: `/repositories/:user/:repoId/changes`, - // params: {repoId: repo.name,user}, - // query: { - // ref: reference.name, - // prefix: entry.path, - // } - // } - // } - - // const uriNavigator = { - // return { - // pathname: '/repositories/:user/:repoId/changes', - // params: params, - // query: { ref: reference.name, prefix: query.path ?? "" }, - // }; - // } } downloadUrl={undefined}/> const changesTreeMessage =

Showing changes for branch {reference.name}

- // const committedRef = reference.id + "@" - // const uncommittedRef = reference.id const actionErrorDisplay = (actionError) ? setActionError(null)}/> : <> @@ -276,6 +253,7 @@ const ChangesBrowser: React.FC = ({repo, reference, prefix, {deleteState.error && setDeleteState(initialState)}/>} ; if(commitId){ - for (let i = 0; i < response.data.length; i++) { - let found = changes.data.find(item => item.path === response.data[i].name); - if (found) { - response.data[i].action = found.action; - } - } - for (let i = 0; i < changes.data.length; i++) { - let found = response.data.find(item => item.name === changes.data[i].path); - if (!found) { - let newObj = {...changes.data[i]}; - newObj.name = newObj.path - for (let key in response.data[0]) { - if (!newObj.hasOwnProperty(key)) { - newObj[key] = ''; - } - } - response.data.push(newObj); - } - } + getActions(changes,response) } if (error) return ; diff --git a/src/pages/repositories/repository/repo-comp/objects/uplodaButton.tsx b/src/pages/repositories/repository/repo-comp/objects/uplodaButton.tsx index 4b23982..15c12cc 100644 --- a/src/pages/repositories/repository/repo-comp/objects/uplodaButton.tsx +++ b/src/pages/repositories/repository/repo-comp/objects/uplodaButton.tsx @@ -14,11 +14,11 @@ import { object } from "../../../../../lib/api/interface/index"; const MAX_PARALLEL_UPLOADS = 1; const destinationPath = (path: string | undefined, file: _File) => { - return `${path ? path : ""}${file.path.replace(/\\/g, '/').replace(/^\//, '')}`; + return `${path ? path : ""}/${file.path.replace(/\\/g, '/').replace(/^\//, '')}`; }; const UploadCandidate = ({ repoId, path, file, state,setUploadPath,onRemove = null }) => { - const fpath = destinationPath(path, file) + const fpath = destinationPath(path, file) useEffect(()=>{ setUploadPath(fpath) },[path]) @@ -43,7 +43,7 @@ const destinationPath = (path: string | undefined, file: _File) => { - jzfs:/{repoId}{fpath} + jzfs:/{repoId}/{fpath} @@ -107,7 +107,6 @@ export const UploadButton = ({repoId, reference, path,wipID, onDone, onClick, on useEffect(() => { setCurrentPath(path) - }, [path]) useEffect(() =>{ files.length>1? setInputStuts(false):'' diff --git a/src/util/changes.ts b/src/util/changes.ts new file mode 100644 index 0000000..0b6fd91 --- /dev/null +++ b/src/util/changes.ts @@ -0,0 +1,16 @@ +export function getActions(arr1,arr2){ + let Arr1 = getData(arr1); + let Arr2 = getData(arr2); + for (let i = 0; i < Arr2.length; i++) { + let found = Arr1.find(item => item.to_hash === Arr2[i].hash); + if (found) { + Arr2[i].action = found.action; + let fdir = found.path.split('/') + Arr2[i].dir = fdir > 2?fdir.filter((item,index)=>{return index