Compare commits

...

No commits in common. "main" and "typescript" have entirely different histories.

46 changed files with 4344 additions and 4243 deletions

View file

@ -1,3 +1,3 @@
> 1%
last 2 versions
not ie <= 8
not dead

View file

@ -1,5 +0,0 @@
[*.{js,jsx,ts,tsx,vue}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true

View file

@ -3,15 +3,29 @@ module.exports = {
env: {
node: true
},
'extends': [
'plugin:vue/essential',
'@vue/standard'
extends: [
"plugin:vue/essential",
"eslint:recommended",
"@vue/typescript/recommended",
"@vue/prettier",
"@vue/prettier/@typescript-eslint"
],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
},
parserOptions: {
parser: 'babel-eslint'
}
}
ecmaVersion: 2020
},
rules: {
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off"
},
overrides: [
{
files: [
"**/__tests__/*.{j,t}s?(x)",
"**/tests/unit/**/*.spec.{j,t}s?(x)"
],
env: {
jest: true
}
}
]
};

2
.gitignore vendored
View file

@ -2,6 +2,7 @@
node_modules
/dist
# local env files
.env.local
.env.*.local
@ -10,6 +11,7 @@ node_modules
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea

View file

@ -1,2 +1,29 @@
# Rebuilding Platform.sh with Vue.js and Tailwind CSS
# Rebuilding Platform.sh with Vue.js, TypeScript and Tailwind CSS
## Project setup
```
yarn install
```
### Compiles and hot-reloads for development
```
yarn serve
```
### Compiles and minifies for production
```
yarn build
```
### Run your unit tests
```
yarn test:unit
```
### Lints and fixes files
```
yarn lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

3
assets/css/tailwind.pcss Normal file
View file

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View file

@ -1,5 +1,3 @@
module.exports = {
presets: [
'@vue/app'
]
}
presets: ["@vue/cli-plugin-babel/preset"]
};

View file

@ -1,30 +1,3 @@
module.exports = {
moduleFileExtensions: [
'js',
'jsx',
'json',
'vue'
],
transform: {
'^.+\\.vue$': 'vue-jest',
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
'^.+\\.jsx?$': 'babel-jest'
},
transformIgnorePatterns: [
'/node_modules/'
],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1'
},
snapshotSerializers: [
'jest-serializer-vue'
],
testMatch: [
'**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
],
testURL: 'http://localhost/',
watchPlugins: [
'jest-watch-typeahead/filename',
'jest-watch-typeahead/testname'
]
}
preset: "@vue/cli-plugin-unit-jest/presets/typescript-and-babel"
};

View file

@ -5,35 +5,39 @@
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"test:unit": "vue-cli-service test:unit"
"test:unit": "vue-cli-service test:unit",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^2.6.5",
"postcss": "^7.0.17",
"sugarss": "^2.0.0",
"tailwindcss-interaction-variants": "^2.0.0-beta.1",
"tailwindcss-spaced-items": "^0.1.0",
"tailwindcss-transforms": "^2.2.0",
"tailwindcss-visuallyhidden": "^1.0.2",
"vue": "^2.6.10",
"vue-router": "^3.1.0"
"@tailwindcss/postcss7-compat": "^2.0.2",
"autoprefixer": "^9",
"core-js": "^3.6.5",
"postcss": "^7",
"tailwindcss": "npm:@tailwindcss/postcss7-compat",
"tailwindcss-interaction-variants": "^5.0.0",
"vue": "^2.6.11",
"vue-class-component": "^7.2.3",
"vue-property-decorator": "^9.1.2",
"vue-router": "^3.2.0"
},
"devDependencies": {
"@fullhuman/postcss-purgecss": "^1.2.0",
"@vue/cli-plugin-babel": "^3.6.0",
"@vue/cli-plugin-eslint": "^3.6.0",
"@vue/cli-plugin-unit-jest": "^3.6.3",
"@vue/cli-service": "^3.10.0",
"@vue/eslint-config-standard": "^4.0.0",
"@vue/test-utils": "1.0.0-beta.29",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "^10.0.1",
"babel-jest": "^23.6.0",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.2.3",
"postcss-import": "^12.0.1",
"tailwindcss": "^1.0.6",
"vue-template-compiler": "^2.5.21"
"@types/jest": "^24.0.19",
"@typescript-eslint/eslint-plugin": "^2.33.0",
"@typescript-eslint/parser": "^2.33.0",
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-typescript": "~4.5.0",
"@vue/cli-plugin-unit-jest": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/eslint-config-prettier": "^6.0.0",
"@vue/eslint-config-typescript": "^5.0.2",
"@vue/test-utils": "^1.0.3",
"eslint": "^6.7.2",
"eslint-plugin-prettier": "^3.1.3",
"eslint-plugin-vue": "^6.2.2",
"prettier": "^1.19.1",
"typescript": "~3.9.3",
"vue-template-compiler": "^2.6.11"
}
}

View file

@ -1,16 +1,5 @@
module.exports = {
parser: 'sugarss',
plugins: [
require('postcss-import'),
require('tailwindcss'),
require('postcss-nested'),
require('autoprefixer'),
process.env.NODE_ENV === 'production' && require('@fullhuman/postcss-purgecss')({
content: [
'./src/**/*.vue',
'./public/index.html',
],
defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || []
})
require('tailwindcss')
]
}

View file

@ -1,2 +0,0 @@
https://rebuilding-platformsh.netlify.com/* https://rebuilding-platformsh.oliverdavies.uk/:splat 301!

View file

@ -1,16 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>rebuilding-platformsh</title>
<title><%= htmlWebpackPlugin.options.title %></title>
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600,700" rel="stylesheet">
</head>
<body>
<noscript>
<strong>We're sorry but rebuilding-platformsh doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->

View file

@ -1,29 +1,16 @@
<template>
<div class="min-h-screen antialiased font-sans bg-gray-200">
<div id="app" class="min-h-screen antialiased font-sans bg-gray-200">
<alert-message>
<p>
A clone of <a href="https://platform.sh">Platform.sh</a>s new hosting dashboard.<br class="hidden sm:inline">
Built with <a href="https://vuejs.org">Vue.js</a>
and <a href="https://tailwindcss.com">Tailwind CSS</a>
by <a href="https://www.oliverdavies.uk">Oliver Davies</a>.
<!-- eslint-disable-next-line -->
A clone of <a href="https://platform.sh">Platform.sh</a>s hosting dashboard.<br class="hidden sm:inline" />
<!-- eslint-disable-next-line -->
Built with <a href="https://vuejs.org">Vue.js</a> and <a href="https://tailwindcss.com">Tailwind CSS</a> by <a href="https://www.oliverdavies.uk">Oliver Davies</a>.
</p>
</alert-message>
<router-view :projects="projects" ></router-view>
<router-view />
</div>
</template>
<style src="./assets/css/tailwind.css"></style>
<script>
import projects from './data/projects.json'
export default {
data () {
return {
title: 'Rebuilding Platform.sh',
projects
}
}
}
</script>
<style src="../assets/css/tailwind.pcss" lang="postcss" />

View file

@ -1,2 +0,0 @@
a:hover
@apply underline

View file

@ -1 +0,0 @@
@import './components/search-form.css'

View file

@ -1,3 +0,0 @@
.search-form
> input:focus + svg
@apply opacity-100

View file

@ -1,7 +0,0 @@
@import 'tailwindcss/base'
@import './base.css'
@import 'tailwindcss/components'
@import './components.css'
@import 'tailwindcss/utilities'

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 477 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 237 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

View file

@ -1,14 +0,0 @@
<template>
<section class="bg-gun-powder p-3 text-center text-white text-sm font-semibold">
<slot></slot>
</section>
</template>
<style type="postcss" scoped>
a
@apply underline
&:hover,
&:focus
@apply no-underline
</style>

View file

@ -1,27 +0,0 @@
<template>
<div>
<header class="bg-gray-900 text-white pt-4 pb-12">
<div class="container mx-auto px-4">
<div class="flex-1 flex justify-between items-center -mx-4">
<div class="w-1/7 px-4">
<router-link :to="{ name: 'projects' }">
<svg alt="icon" class="w-6 h-6" viewBox="0 0 28 28" version="1.1" xmlns="http://www.w3.org/2000/svg"><defs><polygon id="path-1" points="0 0 27.6677333 0 27.6677333 11.0021333 0 11.0021333"></polygon><polygon id="path-3" points="0 0.0373333333 27.6677333 0.0373333333 27.6677333 3.7744 0 3.7744"></polygon><polygon id="path-5" points="0 0.365866667 27.6677333 0.365866667 27.6677333 6.01066667 0 6.01066667"></polygon></defs><g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g transform="translate(-61.000000, -43.000000)"><g transform="translate(61.000000, 43.000000)"><g><mask id="mask-2" fill="white"><use xlink:href="#path-1"></use></mask><g></g><polygon fill="#ffffff" mask="url(#mask-2)" points="-1.86666667 12.8688 29.5344 12.8688 29.5344 -1.86666667 -1.86666667 -1.86666667"></polygon></g><g transform="translate(0.000000, 23.893333)"><mask id="mask-4" fill="white"><use xlink:href="#path-3"></use></mask><polygon fill="#ffffff" mask="url(#mask-4)" points="-1.86666667 5.64106667 29.5344 5.64106667 29.5344 -1.82933333 -1.86666667 -1.82933333"></polygon></g><g transform="translate(0.000000, 14.186667)"><mask id="mask-6" fill="white"><use xlink:href="#path-5"></use></mask><polygon fill="#ffffff" mask="url(#mask-6)" points="-1.86666667 7.87733333 29.5344 7.87733333 29.5344 -1.5008 -1.86666667 -1.5008"></polygon></g></g></g></g></svg>
</router-link>
</div>
<slot name="banner-left"></slot>
<div class="flex justify-end px-4">
<button type="button" class="w-full inline-flex py-1 px-2 rounded font-semibold hover:bg-gray-700">
Oliver Davies
<svg class="ml-2 w-6 h-6" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M6.90002 9.8999C6.90002 9.5999 7.00002 9.3999 7.20002 9.1999C7.60002 8.7999 8.20002 8.7999 8.60002 9.1999L12.1 12.6999L15.6 9.1999C16 8.7999 16.6 8.7999 17 9.1999C17.4 9.5999 17.4 10.1999 17 10.5999L12.8 14.7999C12.4 15.1999 11.8 15.1999 11.4 14.7999L7.20002 10.5999C7.00002 10.3999 6.90002 10.1999 6.90002 9.8999Z" fill="#ffffff"></path></svg>
</button>
</div>
</div>
</div>
</header>
<div class="container mx-auto px-4 py-3 -mt-8 mb-4 bg-charade shadow-lg">
<slot name="sub-banner"></slot>
</div>
</div>
</template>

View file

@ -1,5 +0,0 @@
<template>
<h1 class="font-bold text-2xl text-gray-800">
<slot></slot>
</h1>
</template>

View file

@ -1,22 +0,0 @@
<template>
<div class="flex-1 flex items-center text-xs">
<ul class="flex spaced-x-1">
<li class="flex items-center spaced-x-1">
<router-link :to="{ name: 'projects' }" class="font-semibold text-white opacity-75">Projects</router-link>
<svg class="h-6 w-6 fill-current text-white opacity-75 -rotate-90" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M6.9 9.9c0-.3.1-.5.3-.7.4-.4 1-.4 1.4 0l3.5 3.5 3.5-3.5c.4-.4 1-.4 1.4 0 .4.4.4 1 0 1.4l-4.2 4.2c-.4.4-1 .4-1.4 0l-4.2-4.2c-.2-.2-.3-.4-.3-.7z"/></svg>
</li>
<li class="flex items-center font-semibold" v-text="project.name"/>
</ul>
</div>
</template>
<script>
export default {
props: {
project: {
type: Object,
required: true
}
}
}
</script>

View file

@ -1,37 +0,0 @@
<template>
<article>
<router-link :to="{ name: 'project', params: { id: project.id }}" class="group block hover:no-underline">
<span class="block bg-gray-100 shadow-lg rounded overflow-hidden">
<span class="block p-6">
<h2 class="font-bold text-gray-800 group-hover:underline" v-text="project.name"/>
<p class="text-gray-600" v-text="project.owner"/>
<img v-bind="{
alt: `Screenshot of ${project.name}`,
src: projectImage
}" class="w-full mt-4 rounded shadow-2xl" aria-hidden/>
</span>
<span class="-mt-10 py-5 px-8 block relative bg-white">
<p v-text="project.region"/>
</span>
</span>
</router-link>
</article>
</template>
<script>
export default {
props: {
project: {
type: Object,
required: true
}
},
computed: {
projectImage () {
return require(`@/assets/img/screenshots/${this.project.image}`)
}
}
}
</script>

View file

@ -1,17 +0,0 @@
<template>
<div class="flex justify-between items-center -mx-4">
<div class="px-4 flex-1">
<form action="" class="search-form flex flex-row-reverse items-center">
<input class="w-full text-sm bg-inherit text-white focus:outline-none" type="text" placeholder="Search projects">
<svg class="fill-current text-white h-4 w-4 mr-3 opacity-50" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><mask id="project-search-input-mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="16" height="16"><path fill-rule="evenodd" clip-rule="evenodd" d="M11.8 10.3L15.7 14.2C16 14.6 16 15.2 15.6 15.6C15.2 16 14.6 16 14.2 15.6L10.3 11.7C9.3 12.5 7.9 13 6.5 13C2.9 13 0 10.1 0 6.50005C0 2.90005 2.9 4.57764e-05 6.5 4.57764e-05C10.1 4.57764e-05 13 2.90005 13.1 6.50005C13.1 7.90005 12.6 9.20005 11.8 10.3ZM2 6.50005C2 9.00005 4 11 6.5 11C9 11 11 9.00005 11 6.50005C11 4.00005 9 2.00005 6.5 2.00005C4 2.00005 2 4.00005 2 6.50005Z" fill="#32324c"></path></mask><g mask="url(#project-search-input-mask0)"><rect x="-4" y="-3.99995" width="24" height="24"></rect></g></svg>
</form>
</div>
<div class="px-4">
<a href="#0" class="inline-flex flex-row-reverse items-center px-4 py-2 rounded text-white text-sm bg-blue-700 hocus:bg-blue-800">
Add project
<svg class="h-3 w-4" xmlns="http://www.w3.org/2000/svg"><path d="M6 6v4H4V6H0V4h4V0h2v4h4v2z" fill="#fff" fill-rule="evenodd"/></svg>
</a>
</div>
</div>
</template>

View file

@ -1,34 +0,0 @@
<template>
<div>
<button
type="button"
class="p-2 text-gray-700 hover:bg-white hover:rounded hover:shadow"
:class="{ 'bg-white rounded shadow text-blue-400': mode == 'grid'}"
@click="$emit('changed', 'grid')"
>
<span class="visuallyhidden">View projects in a grid</span>
<svg class="w-6 h-6 fill-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22"><defs><clipPath id="a"><path d="M12.2 5v4.8H17V5zm0 12H17v-4.8h-4.8zM5 5h4.8v4.8H5zm0 12v-4.8h4.8V17z" fill="none" clip-rule="evenodd"/></clipPath><clipPath id="b"><path fill="none" d="M0 0h22v22H0z"/></clipPath><clipPath id="c"><path fill="none" d="M5 5h12v12H5z"/></clipPath></defs><g clip-path="url(&quot;#a&quot;)"><g clip-path="url(&quot;#b&quot;)" style="clip-path:url(&quot;#icon-grid-b&quot;)"><g clip-path="url(&quot;#c&quot;)"><path d="M0 0h22v22H0z"/></g></g></g></svg>
</button>
<button
type="button"
class="ml-2 p-2 text-gray-700 hover:bg-white hover:rounded hover:shadow"
:class="{ 'bg-white rounded shadow text-blue-400': mode == 'list'}"
@click="$emit('changed', 'list')"
>
<span class="visuallyhidden">View projects in a list</span>
<svg class="w-6 h-6 fill-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 22"><defs><clipPath id="link-icon-a"><path d="M5,5V7H19V5Zm14,7V10H5v2ZM5,17H19V15H5Z" style="fill: none; clip-rule: evenodd;"></path></clipPath><clipPath id="link-icon-b"><rect width="24" height="22" style="fill: none;"></rect></clipPath><clipPath id="link-icon-c"><rect x="5" y="5" width="14" height="12" style="fill: none;"></rect></clipPath></defs><title>Asset 1</title><g style="clip-path: url(&quot;#link-icon-a&quot;);"><g style="clip-path: url(&quot;#link-icon-b&quot;);"><g style="clip-path: url(&quot;#link-icon-c&quot;);"><rect width="24" height="22"></rect></g></g></g></svg>
</button>
</div>
</template>
<script>
export default {
props: {
mode: {
type: String,
required: true
}
}
}
</script>

View file

@ -0,0 +1,14 @@
<template>
<section
class="bg-gun-powder p-3 text-center text-white text-sm font-semibold"
>
<slot></slot>
</section>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
@Component
export default class AlertMessage extends Vue {}
</script>

View file

@ -1,23 +0,0 @@
[
{
"id": "1",
"name": "Inviqa",
"owner": "inviqa",
"region": "Europe (West 1)",
"image": "inviqa.jpeg"
},
{
"id": "2",
"name": "oliverdavies.uk",
"owner": "Oliver Davies",
"region": "Europe (West 1)",
"image": "oliver-davies.png"
},
{
"id": "3",
"name": "PHP South Wales",
"owner": "PHP South Wales organisers",
"region": "Europe (West 1)",
"image": "php-south-wales.png"
}
]

View file

@ -1,14 +0,0 @@
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
Vue.component('alert-message', require('@/components/AlertMessage').default)
Vue.component('banner', require('@/components/Banner').default)
Vue.component('page-title', require('@/components/PageTitle').default)
new Vue({
router,
render: h => h(App)
}).$mount('#app')

13
src/main.ts Normal file
View file

@ -0,0 +1,13 @@
import Vue from "vue";
import AlertMessage from "@/components/alert-message.vue";
import App from "./App.vue";
import router from "./router";
Vue.config.productionTip = false;
Vue.component("AlertMessage", AlertMessage);
new Vue({
router,
render: h => h(App)
}).$mount("#app");

View file

@ -1,24 +0,0 @@
import Vue from 'vue'
import Router from 'vue-router'
import Project from '@/views/Project'
import Projects from '@/views/Projects'
Vue.use(Router)
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'projects',
component: Projects
},
{
path: '/project/:id',
name: 'project',
component: Project,
props: true
}
]
})

21
src/router/index.ts Normal file
View file

@ -0,0 +1,21 @@
import Vue from "vue";
import VueRouter, { RouteConfig } from "vue-router";
import Home from "../views/Home.vue";
Vue.use(VueRouter);
const routes: Array<RouteConfig> = [
{
path: "/",
name: "Home",
component: Home
}
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
export default router;

13
src/shims-tsx.d.ts vendored Normal file
View file

@ -0,0 +1,13 @@
import Vue, { VNode } from "vue";
declare global {
namespace JSX {
// tslint:disable no-empty-interface
interface Element extends VNode {}
// tslint:disable no-empty-interface
interface ElementClass extends Vue {}
interface IntrinsicElements {
[elem: string]: any;
}
}
}

4
src/shims-vue.d.ts vendored Normal file
View file

@ -0,0 +1,4 @@
declare module "*.vue" {
import Vue from "vue";
export default Vue;
}

11
src/views/Home.vue Normal file
View file

@ -0,0 +1,11 @@
<template>
<div class="home">
<h1>Rebuilding Platform.sh</h1>
</div>
</template>
<script lang="ts">
import { Vue } from "vue-property-decorator";
export default class Home extends Vue {}
</script>

View file

@ -1,51 +0,0 @@
<template>
<div>
<banner>
<template #banner-left>
<project-breadcrumb :project="project"/>
</template>
<template #sub-banner>
<span class="text-white">Project and environment dropdowns</span>
</template>
</banner>
<div class="container mx-auto px-4">
<div class="flex items-center">
<div class="w-1/2">
<nav>
<a class="py-2 text-gray-900 text-xs uppercase tracking-widest border-b-2 border-gray-900 font-semibold" href="#">Overview</a>
<a class="ml-6 py-2 text-gray-900 text-xs uppercase tracking-widest" href="#">Settings</a>
</nav>
</div>
<div class="w-1/2 flex items-center justify-end">
<button type="button" class="py-1 pl-2 pr-4 flex items-center text-sm uppercase tracking-wider border border-periwinkle">
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 block fill-current text-gray-700"><path d="M6.90002 9.8999C6.90002 9.5999 7.00002 9.3999 7.20002 9.1999C7.60002 8.7999 8.20002 8.7999 8.60002 9.1999L12.1 12.6999L15.6 9.1999C16 8.7999 16.6 8.7999 17 9.1999C17.4 9.5999 17.4 10.1999 17 10.5999L12.8 14.7999C12.4 15.1999 11.8 15.1999 11.4 14.7999L7.20002 10.5999C7.00002 10.3999 6.90002 10.1999 6.90002 9.8999Z"></path></svg>
<span class="ml-1">Git</span>
</button>
<button type="button" class="ml-3 py-1 pl-2 pr-4 flex items-center text-sm uppercase tracking-wider border border-periwinkle">
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 block fill-current text-gray-700"><path d="M6.90002 9.8999C6.90002 9.5999 7.00002 9.3999 7.20002 9.1999C7.60002 8.7999 8.20002 8.7999 8.60002 9.1999L12.1 12.6999L15.6 9.1999C16 8.7999 16.6 8.7999 17 9.1999C17.4 9.5999 17.4 10.1999 17 10.5999L12.8 14.7999C12.4 15.1999 11.8 15.1999 11.4 14.7999L7.20002 10.5999C7.00002 10.3999 6.90002 10.1999 6.90002 9.8999Z"></path></svg>
<span class="ml-1">CLI</span>
</button>
</div>
</div>
</div>
</div>
</template>
<script>
import ProjectBreadcrumb from '@/components/ProjectBreadcrumb'
export default {
components: {
ProjectBreadcrumb
},
computed: {
project () {
return this.$attrs.projects[this.$attrs.id - 1]
}
}
}
</script>

View file

@ -1,95 +0,0 @@
<template>
<div>
<banner>
<template #sub-banner>
<project-search/>
</template>
</banner>
<main class="container mx-auto p-6">
<div class="flex justify-between items-baseline">
<page-title>All Projects</page-title>
<project-view-switcher @changed="projectViewSwitched" :mode="displayMode"></project-view-switcher>
</div>
<div class="mt-6">
<div
v-if="displayMode == 'grid'"
class="
grid gap-8
md:grid-cols-2
xl:grid-cols-3
"
>
<div
v-for="project in projects"
:key="project.id"
>
<project-card :project="project"/>
</div>
</div>
</div>
<div v-if="displayMode == 'list'" class="pt-6 pb-6 mt-4 bg-white shadow-md">
<table class="w-full">
<thead>
<tr class="border-b border-gray-300">
<th class="w-1/2 pb-3 px-6 font-semibold text-left text-sm">Project name</th>
<th class="pb-3 px-6 font-semibold text-left text-sm">Owner</th>
<th class="w-1/4 pb-3 px-6 font-semibold text-left text-sm">Region</th>
</tr>
</thead>
<tbody>
<tr v-for="project in projects" :key="project.id">
<td class="px-6 py-4">
<router-link :to="{ name: 'project', params: { id: project.id }}" class="font-semibold text-sm hover:underline">{{ project.name }}</router-link>
</td>
<td class="px-6 py-4">
<a href="#0" class="font-semibold text-sm hover:underline">{{ project.owner }}</a>
</td>
<td class="px-6 py-4">
<a href="#0" class="font-semibold text-sm hover:underline">{{ project.region }}</a>
</td>
</tr>
</tbody>
</table>
</div>
</main>
</div>
</template>
<script>
import ProjectCard from '@/components/ProjectCard'
import ProjectSearch from '@/components/ProjectSearch'
import ProjectViewSwitcher from '@/components/ProjectViewSwitcher'
export default {
name: 'projects',
props: {
projects: {
type: Object,
required: true
}
},
components: {
ProjectCard,
ProjectSearch,
ProjectViewSwitcher
},
data () {
return {
displayMode: 'grid'
}
},
methods: {
projectViewSwitched (mode) {
this.displayMode = mode
}
}
}
</script>

View file

@ -1,5 +1,6 @@
const { variants } = require('tailwindcss/defaultConfig')
const { fontFamily, spacing } = require('tailwindcss/defaultTheme')
const { variants } = require('tailwindcss/defaultConfig');
const { fontFamily } = require('tailwindcss/defaultTheme');
const variationPlugin = require('tailwindcss-interaction-variants');
module.exports = {
theme: {
@ -26,9 +27,6 @@ module.exports = {
textDecoration: [...variants.textDecoration, 'group-hover', 'hocus', 'group-hocus']
},
plugins: [
require('tailwindcss-interaction-variants')(),
require('tailwindcss-spaced-items')({ values: spacing }),
require('tailwindcss-transforms')(),
require('tailwindcss-visuallyhidden')()
variationPlugin
]
}

View file

@ -1,5 +0,0 @@
module.exports = {
env: {
jest: true
}
}

View file

@ -1,12 +0,0 @@
import { shallowMount } from '@vue/test-utils'
import HelloWorld from '@/components/HelloWorld.vue'
describe('HelloWorld.vue', () => {
it('renders props.msg when passed', () => {
const msg = 'new message'
const wrapper = shallowMount(HelloWorld, {
propsData: { msg }
})
expect(wrapper.text()).toMatch(msg)
})
})

View file

@ -0,0 +1,12 @@
import { shallowMount } from "@vue/test-utils";
import HelloWorld from "@/components/HelloWorld.vue";
describe("HelloWorld.vue", () => {
it("renders props.msg when passed", () => {
const msg = "new message";
const wrapper = shallowMount(HelloWorld, {
propsData: { msg }
});
expect(wrapper.text()).toMatch(msg);
});
});

41
tsconfig.json Normal file
View file

@ -0,0 +1,41 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env",
"jest"
],
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}

7839
yarn.lock

File diff suppressed because it is too large Load diff