Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/dev-main-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: dev-main-build

on:
push:
branches: [ dev ]
paths: 'frontend/main'
pull_request:
branches: [ dev ]
paths: 'frontend/main'


# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest

# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
- name: Setup Node.js environment
uses: actions/setup-node@v2.1.4
with:
node-version: 12
- run: npm install
- run: npm run build
12 changes: 4 additions & 8 deletions frontend/admin/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,14 @@
"extends": [
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"plugin:prettier/recommended"
"plugin:prettier/recommended",
"plugin:prettier/react",
"plugin:prettier/@typescript-eslint"
],
"plugins": ["@typescript-eslint", "react", "prettier"],
"rules": {
"react/react-in-jsx-scope": "off",
"react/display-name": 0,
"no-restricted-imports": [
"error",
{
"patterns": ["../*"]
}
]
"import/no-relative-parent-imports": "error"
},
"globals": {
"React": "writable"
Expand Down
20 changes: 4 additions & 16 deletions frontend/admin/next.config.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,9 @@
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
const withBundleAnalyzer = require("@next/bundle-analyzer")({
enabled: process.env.ANALYZE === "true",
});
module.exports = withBundleAnalyzer({
images: {
loader: 'cloudinary',
path: 'https://media.codingcat.dev/image/upload/',
},
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
if (!isServer) {
config.node = {
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty',
};
}
return config;
loader: "cloudinary",
path: "https://media.codingcat.dev/images/",
},
});
2 changes: 1 addition & 1 deletion frontend/admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"analyze": "cross-env ANALYZE=true next build",
"analyze:server": "cross-env BUNDLE_ANALYZE=server next build",
"analyze:browser": "cross-env BUNDLE_ANALYZE=browser next build",
"lint": "eslint . --quiet --ext .ts,.tsx"
"lint": "eslint . --quiet --ext .ts,.tsx && tsc --noEmit"
},
"dependencies": {
"@emotion/cache": "^11.1.3",
Expand Down
4 changes: 2 additions & 2 deletions frontend/admin/src/components/ActiveLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { withRouter } from 'next/router';
import Link from 'next/link';
import React, { Children } from 'react';

function ActiveLink({ router, children, ...props }: any) {
const ActiveLink = ({ router, children, ...props }) => {
const child = Children.only(children);

let className = child.props.className || '';
Expand All @@ -17,6 +17,6 @@ function ActiveLink({ router, children, ...props }: any) {
{React.cloneElement(child, { className })}
</Link>
);
}
};

export default withRouter(ActiveLink);
270 changes: 270 additions & 0 deletions frontend/admin/src/components/Admin/AdminMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
import Link from 'next/link';

import Blog from '../global/icons/Blog';
import Community from '../global/icons/Community';
import Courses from '../global/icons/Courses';
import Podcasts from '../global/icons/Podcasts';
import Tutorials from '../global/icons/Tutorials';

export default function AdminMenu({ router }) {
return (
<>
{/* Off-canvas menu for mobile, show/hide based on off-canvas menu state. */}
<div className="md:hidden">
<div className="fixed inset-0 flex z-40">
{/*
Off-canvas menu overlay, show/hide based on off-canvas menu state.

Entering: "transition-opacity ease-linear duration-300"
From: "opacity-0"
To: "opacity-100"
Leaving: "transition-opacity ease-linear duration-300"
From: "opacity-100"
To: "opacity-0"
*/}
<div className="fixed inset-0" aria-hidden="true">
<div className="absolute inset-0 bg-ccd-basics-600 opacity-75" />
</div>
{/*
Off-canvas menu, show/hide based on off-canvas menu state.

Entering: "transition ease-in-out duration-300 transform"
From: "-translate-x-full"
To: "translate-x-0"
Leaving: "transition ease-in-out duration-300 transform"
From: "translate-x-0"
To: "-translate-x-full"
*/}
<div className="relative flex-1 flex flex-col max-w-xs w-full pt-5 pb-4 bg-ccd-basics-800">
<div className="absolute top-0 right-0 -mr-12 pt-2">
<button className="ml-1 flex items-center justify-center h-10 w-10 rounded-full focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white">
<span className="sr-only">Close sidebar</span>
{/* Heroicon name: x */}
<svg
className="h-6 w-6 text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
aria-hidden="true"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</div>
<div className="flex-shrink-0 flex items-center px-4">
<img
className="h-8 w-auto"
src="https://tailwindui.com/img/logos/workflow-logo-indigo-500-mark-white-text.svg"
alt="Workflow"
/>
</div>
<div className="mt-5 flex-1 h-0 overflow-y-auto">
<nav className="px-2 space-y-1">
<a
href="#"
className="group flex items-center px-2 py-2 text-base font-medium rounded-md text-white bg-ccd-basics-900"
>
{/* Heroicon name: home */}
<svg
className="mr-4 h-6 w-6 text-ccd-basics-300"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
aria-hidden="true"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
/>
</svg>
Dashboard
</a>
<a
href="#"
className="group flex items-center px-2 py-2 text-base font-medium rounded-md text-ccd-basics-300 hover:text-white hover:bg-ccd-basics-700"
>
{/* Heroicon name: users */}
<svg
className="mr-4 h-6 w-6 text-ccd-basics-400 group-hover:text-ccd-basics-300"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
aria-hidden="true"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"
/>
</svg>
Team
</a>
<a
href="#"
className="group flex items-center px-2 py-2 text-base font-medium rounded-md text-ccd-basics-300 hover:text-white hover:bg-ccd-basics-700"
>
{/* Heroicon name: folder */}
<svg
className="mr-4 h-6 w-6 text-ccd-basics-400 group-hover:text-ccd-basics-300"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
aria-hidden="true"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"
/>
</svg>
Projects
</a>
<a
href="#"
className="group flex items-center px-2 py-2 text-base font-medium rounded-md text-ccd-basics-300 hover:text-white hover:bg-ccd-basics-700"
>
{/* Heroicon name: calendar */}
<svg
className="mr-4 h-6 w-6 text-ccd-basics-400 group-hover:text-ccd-basics-300"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
aria-hidden="true"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
/>
</svg>
Calendar
</a>
<a
href="#"
className="group flex items-center px-2 py-2 text-base font-medium rounded-md text-ccd-basics-300 hover:text-white hover:bg-ccd-basics-700"
>
{/* Heroicon name: inbox */}
<svg
className="mr-4 h-6 w-6 text-ccd-basics-400 group-hover:text-ccd-basics-300"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
aria-hidden="true"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4"
/>
</svg>
Documents
</a>
<a
href="#"
className="group flex items-center px-2 py-2 text-base font-medium rounded-md text-ccd-basics-300 hover:text-white hover:bg-ccd-basics-700"
>
{/* Heroicon name: chart-bar */}
<svg
className="mr-4 h-6 w-6 text-ccd-basics-400 group-hover:text-ccd-basics-300"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
aria-hidden="true"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
/>
</svg>
Reports
</a>
</nav>
</div>
</div>
<div className="flex-shrink-0 w-14" aria-hidden="true">
{/* Dummy element to force sidebar to shrink to fit close icon */}
</div>
</div>
</div>
{/* Static sidebar for desktop */}
<div className="hidden md:flex md:flex-shrink-0">
<div className="flex flex-col w-64">
{/* Sidebar component, swap this element with another sidebar if you like */}
<div className="flex flex-col h-0 flex-1 ">
<div className="flex items-center h-16 flex-shrink-0 px-4 bg-ccd-basics-900 text-white">
<Link href="/admin">
<a>
<div>Dashboard</div>
</a>
</Link>
</div>
<div className="flex-1 flex flex-col overflow-y-auto">
<nav className="flex-1 px-2 py-4 bg-ccd-basics-800 space-y-1">
<Link href="/admin/courses">
<a className="group flex items-center px-2 py-2 text-sm font-medium text-ccd-basics-300 rounded-md hover:text-white hover:bg-ccd-basics-700">
<div className="mr-3 h-6 w-6 text-ccd-basics-400 group-hover:text-ccd-basics-300 flex flex-col justify-content h-full">
<Courses />
</div>
Courses
</a>
</Link>
<Link href="/admin/tutorials">
<a className="group flex items-center px-2 py-2 text-sm font-medium text-ccd-basics-300 rounded-md hover:text-white hover:bg-ccd-basics-700">
<div className="mr-3 h-6 w-6 text-ccd-basics-400 group-hover:text-ccd-basics-300 flex flex-col justify-content h-full">
<Tutorials />
</div>
Tutorials
</a>
</Link>
<Link href="/admin/blog">
<a className="group flex items-center px-2 py-2 text-sm font-medium text-white rounded-md hover:bg-ccd-basics-700">
<div className="mr-3 h-6 w-6 text-ccd-basics-400 group-hover:text-ccd-basics-300 flex flex-col justify-content h-full ">
<Blog />
</div>
Blog
</a>
</Link>
<Link href="/admin/podcasts">
<a className="group flex items-center px-2 py-2 text-sm font-medium text-ccd-basics-300 rounded-md hover:text-white hover:bg-ccd-basics-700">
<div className="mr-3 h-6 w-6 text-ccd-basics-400 group-hover:text-ccd-basics-300 flex flex-col justify-content h-full">
<Podcasts />
</div>
Podcasts
</a>
</Link>
<Link href="/admin/community">
<a className="group flex items-center px-2 py-2 text-sm font-medium text-ccd-basics-300 rounded-md hover:text-white hover:bg-ccd-basics-700">
<div className="mr-3 h-6 w-6 text-ccd-basics-400 group-hover:text-ccd-basics-300 flex flex-col justify-content h-full">
<Community />
</div>
Community
</a>
</Link>
</nav>
</div>
</div>
</div>
</div>
</>
);
}
Loading