Skip to content

Commit

Permalink
feat: visual schema and test CI (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
manolo-battista authored Jun 27, 2023
1 parent 2b5fafa commit 8dbd86c
Show file tree
Hide file tree
Showing 20 changed files with 1,411 additions and 70 deletions.
5 changes: 4 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"plugins": ["prettier"],
"extends": ["next/core-web-vitals", "plugin:prettier/recommended"]
"extends": ["next/core-web-vitals", "plugin:prettier/recommended"],
"rules": {
"react-hooks/exhaustive-deps": "off"
}
}
31 changes: 31 additions & 0 deletions .github/workflows/check-copyright-license.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Workflow name
name: 'Check copyright license on files'

# Event for the workflow
on:
workflow_call:
inputs:
company:
description: Company name owner of the license
required: true
type: string
extensions:
description: Extensions list where license will add
required: true
type: string

# List of jobs
jobs:
Check-Copyright-License:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-go@v4
with:
go-version: '1.20.4'
- run: go install github.com/google/addlicense@latest
- run: addlicense -c '${{ inputs.company }}' -l apache ${{ inputs.extensions }}
- run: git status --porcelain
- run: git diff --exit-code
21 changes: 16 additions & 5 deletions .github/workflows/pr-build-test.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

# Workflow name
name: 'Build and Test'

Expand All @@ -11,21 +10,33 @@ on:

# List of jobs
jobs:
Check-License:
uses: ./.github/workflows/check-copyright-license.yml
with:
company: Arkemis S.r.l.
extensions: ./**/*.js ./**/*.ts ./**/*.tsx ./**/*.css
Build-Test:
runs-on: ubuntu-latest
needs: Check-License
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup pnpm
uses: pnpm/action-setup@v2.2.1
with:
version: 8.6.1
version: latest
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build package
run: pnpm build
- name: Test
run: pnpm test -- --coverage --bail --detectOpenHandles
# - name: Upload coverage reports to Codecov
# uses: codecov/codecov-action@v3
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage/cobertura-coverage.xml
directory: coverage
fail_ci_if_error: true
verbose: true
18 changes: 17 additions & 1 deletion arke/getClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@
* limitations under the License.
*/

import { Client, TToken } from "@arkejs/client";
import { Client, HTTPStatusCode, TToken } from "@arkejs/client";
import { GetServerSidePropsContext } from "next";
import { getSession } from "next-auth/react";
import { getToken } from "next-auth/jwt";
import { getCookie } from "cookies-next";
import { getCookieName } from "../utils/auth";
import toast from "react-hot-toast";

const getServerUrl = () => {
if (
Expand Down Expand Up @@ -60,5 +61,20 @@ export const getClient = (context?: {
}
return getSession() as Promise<TToken>;
},
httpClientConfig: (api) => {
api.interceptors.request.use((config) => config);
api.interceptors.response.use(
(config) => {
return config;
},
(err) => {
if (err.response.status === HTTPStatusCode.InternalServerError) {
toast.error(`${err.message}: ${err.response.data?.errors?.detail}`);
}
return Promise.reject(err);
}
);
return api;
},
});
};
22 changes: 22 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Validate: curl --data-binary @codecov.yml https://codecov.io/validate
codecov:
# set new Default branch
branch: main
# Specify a branch you want Codecov to always only read the YAML from
strict_yaml_branch: main;
# When Codecov generates a comparison for a pull-request, but the pull-request’s base
# does not have coverage information, Codecov will try to find an appropriate substitute (a “pseudo-base”)
allow_pseudo_compare: True

coverage:
status:
project:
default:
target: 70%
threshold: 5%
patch: false

comment:
require_changes: true
layout: "diff, reach"
behavior: default
36 changes: 36 additions & 0 deletions components/Icon/CompassIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* Copyright 2023 Arkemis S.r.l.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

export function CompassIcon({ className }: { className?: string }) {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<path
d="M12 4C10.6193 4 9.5 5.11929 9.5 6.5C9.5 7.88071 10.6193 9 12 9C13.3807 9 14.5 7.88071 14.5 6.5C14.5 5.11929 13.3807 4 12 4ZM12 4V2M21 14.9375C18.8012 17.4287 15.5841 19 12 19C8.41592 19 5.19883 17.4287 3 14.9375M10.7448 8.66169L3 22M13.2552 8.66169L21 22"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
}
36 changes: 36 additions & 0 deletions components/Icon/RemoveIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* Copyright 2023 Arkemis S.r.l.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

export function RemoveIcon({ className }: { className?: string }) {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<path
d="M18 6L6 18M6 6L18 18"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
}
2 changes: 2 additions & 0 deletions components/Sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { CopyIcon, HomeIcon } from "@/components/Icon";
import { Button, Input } from "@arkejs/ui";
import { getCookie } from "cookies-next";
import toast from "react-hot-toast";
import { CompassIcon } from "@/components/Icon/CompassIcon";

function Sidebar() {
const project =
Expand Down Expand Up @@ -74,6 +75,7 @@ function Sidebar() {
<SidebarItem icon={SparklesIcon} label="Arke" href="/arke" />
<SidebarItem icon={TagIcon} label="Parameters" href="/parameters" />
<SidebarItem icon={UserIcon} label="Users" href="/users" />

<SidebarItem
icon={ArrowLeftOnRectangleIcon}
label="Logout"
Expand Down
153 changes: 153 additions & 0 deletions components/VisualSchema/ArkeNode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/**
* Copyright 2023 Arkemis S.r.l.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import React, { memo, useState } from "react";
import { twMerge } from "tailwind-merge";
import { PlusIcon } from "@heroicons/react/24/outline";
import { CrudState } from "@/types/crud";
import toast from "react-hot-toast";
import { TUnit } from "@arkejs/client";
import { AssignParameterAdd } from "@/crud/arke";
import { EditIcon, LinkIcon, TrashIcon } from "@/components/Icon";
import { RemoveIcon } from "@/components/Icon/RemoveIcon";
import { LinkArkeOrGroup } from "@/crud/arke/LinkArkeOrGroup";

interface ArkeNodeProps {
data: {
arke: TUnit;
parameters: TUnit[];
onLoadData(): void;
onEditArke(arke: TUnit): void;
onDeleteArke(arke: TUnit): void;
onUnassignParameter(arke: TUnit, parameter: TUnit): void;
};
}
function ArkeNode(props: ArkeNodeProps) {
const [crud, setCrud] = useState<CrudState & { link: boolean }>({
add: false,
edit: false,
delete: false,
link: false,
});
const {
arke,
parameters,
onLoadData,
onUnassignParameter,
onEditArke,
onDeleteArke,
} = props.data;
const defaults = ["id", "arke_id", "metadata", "inserted_at", "updated_at"];

return (
<div className="arke-node">
<div className="arke-node__header">
<div className="flex w-11/12 items-center">
<div
className={twMerge(
"mr-1 h-[6px] w-[6px] rounded-full",
arke.active ? "bg-success" : "bg-error"
)}
/>
<strong className="truncate">{arke.label}</strong>
<div onClick={() => onEditArke(arke)}>
<EditIcon className="mx-1 w-3 cursor-pointer" />
</div>
</div>
<div className="flex w-1/12 cursor-pointer items-center justify-end">
<div onClick={() => onDeleteArke(arke)}>
<TrashIcon className="w-3 text-error" />
</div>
</div>
</div>
<div className="p-2">
<div
className="flex cursor-pointer items-center underline"
onClick={() => setCrud((p) => ({ ...p, add: true }))}
>
<PlusIcon className="mr-1 w-3" />
Assign new parameter
</div>
<div
className="mb-2 flex cursor-pointer items-center underline"
onClick={() => setCrud((prevState) => ({ ...prevState, link: true }))}
>
<LinkIcon className="mr-1 w-3" />
Connect arke or group
</div>

{parameters.map((item: TUnit & any) => (
<div
key={item.id}
className={twMerge(
"flex items-center",
defaults.includes(item.id) && "text-neutral-400"
)}
>
<div
className="cursor-pointer"
onClick={() => onUnassignParameter(arke, item)}
>
<RemoveIcon
className={twMerge(
"mr-1 w-3 stroke-white",
defaults.includes(item.id) && "invisible"
)}
/>
</div>

{!item.ref ? (
<>
<div className="mr-1">{item.label}</div>
<div>({item.type})</div>
</>
) : (
<div className="flex text-primary">
<div className="mr-1">{item.ref.label}</div>
<div>({item.ref.type})</div>
</div>
)}
</div>
))}
</div>

<AssignParameterAdd
arkeId={arke.id}
linkedParameters={parameters as TUnit[]}
open={crud.add}
onClose={() => setCrud((prevState) => ({ ...prevState, add: false }))}
onSubmit={() => {
toast.success(`Parameters assigned correctly`);
onLoadData();
setCrud((prevState) => ({ ...prevState, add: false }));
}}
/>

<LinkArkeOrGroup
arkeId={arke.id}
open={crud.link}
onClose={() => setCrud((prevState) => ({ ...prevState, link: false }))}
onSubmit={() => {
toast.success(`Link connected correctly`);
onLoadData();
setCrud((prevState) => ({ ...prevState, link: false }));
}}
/>
</div>
);
}

export default memo(ArkeNode);
Loading

0 comments on commit 8dbd86c

Please sign in to comment.