diff --git a/projects/ledge-render/src/lib/components/ledge-card/colors.ts b/projects/ledge-render/src/lib/components/ledge-card/colors.ts new file mode 100644 index 00000000..0a4635a5 --- /dev/null +++ b/projects/ledge-render/src/lib/components/ledge-card/colors.ts @@ -0,0 +1,13 @@ +// random colors +export default [ + "#e55852", + "#e98832", + "#f0d668", + "#47c0af", + "#387fd5", + "#7753df", + "#079948", + "#00A2A1", + "#666666", + "#F37C20", +]; diff --git a/projects/ledge-render/src/lib/components/ledge-card/ledge-card.component.html b/projects/ledge-render/src/lib/components/ledge-card/ledge-card.component.html new file mode 100644 index 00000000..51615922 --- /dev/null +++ b/projects/ledge-render/src/lib/components/ledge-card/ledge-card.component.html @@ -0,0 +1,15 @@ +
+
+
{{ data.header }}
+
+
+

+ {{ cell }} +

+
+
diff --git a/projects/ledge-render/src/lib/components/ledge-card/ledge-card.component.scss b/projects/ledge-render/src/lib/components/ledge-card/ledge-card.component.scss new file mode 100644 index 00000000..727c2b33 --- /dev/null +++ b/projects/ledge-render/src/lib/components/ledge-card/ledge-card.component.scss @@ -0,0 +1,51 @@ +.card { + position: relative; + margin: 0; + padding: 0; + color: rgba(0, 0, 0, 0.65); + font-size: 14px; + font-variant: tabular-nums; + box-sizing: border-box; + line-height: 1.5; + list-style: none; + background-color: #f3f4f5; + border-radius: 2px; + transition: all 0.3s; + // border: 1px solid #e8e8e8; + max-width: 300px; + height: 100%; + &-head { + height: 60px; + padding: 0 24px; + color: rgba(0, 0, 0, 0.85); + font-size: 16px; + border-bottom: 1px solid #e8e8e8; + text-align: center; + .title { + display: inline-block; + flex: 1; + padding: 13px 0; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + font-size: 18px; + font-weight: 600; + font-stretch: normal; + line-height: 1.89; + letter-spacing: 0.75px; + } + } + &-body { + padding: 20px 20px 0 20px; + zoom: 1; + p { + font-size: 14px; + font-style: normal; + line-height: 1.57; + letter-spacing: normal; + text-align: center; + color: #111111; + margin-bottom: 19px; + } + } +} diff --git a/projects/ledge-render/src/lib/components/ledge-card/ledge-card.component.spec.ts b/projects/ledge-render/src/lib/components/ledge-card/ledge-card.component.spec.ts new file mode 100644 index 00000000..3cea5580 --- /dev/null +++ b/projects/ledge-render/src/lib/components/ledge-card/ledge-card.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SkillCardComponent } from './ledge-card.component'; + +describe('SkillCardComponent', () => { + let component: SkillCardComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SkillCardComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SkillCardComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ledge-render/src/lib/components/ledge-card/ledge-card.component.ts b/projects/ledge-render/src/lib/components/ledge-card/ledge-card.component.ts new file mode 100644 index 00000000..06d21d95 --- /dev/null +++ b/projects/ledge-render/src/lib/components/ledge-card/ledge-card.component.ts @@ -0,0 +1,53 @@ +import { Component, OnInit, Input } from "@angular/core"; +import colors from "./colors"; + +interface CardData { + header: string; + cells: string[]; + index?: number; +} + +interface HeaderStyle { + bg: string; + font: string; +} + +@Component({ + selector: "ledge-card", + templateUrl: "./ledge-card.component.html", + styleUrls: ["./ledge-card.component.scss"], +}) +export class SkillCardComponent implements OnInit { + @Input() + data: CardData = { + header: "", + cells: [], + index: -1, + }; + @Input() + headerStyle: HeaderStyle = { + bg: "#fff", + font: "#333", + }; + + constructor() {} + + ngOnInit(): void { + console.log(this.data); + } + + /**TODO */ + getHeaderStyle() { + let idx = this.data.index; + + if (!idx && idx !== 0) { + idx = Math.floor(Math.random() * 10); + } + + return { + "background-color": + (this.headerStyle && this.headerStyle.bg) || colors[idx], + color: (this.headerStyle && this.headerStyle.font) || "#333", + }; + } +} diff --git a/projects/ledge-render/src/lib/ledge-render.component.html b/projects/ledge-render/src/lib/ledge-render.component.html index 281095b8..5690a8c5 100644 --- a/projects/ledge-render/src/lib/ledge-render.component.html +++ b/projects/ledge-render/src/lib/ledge-render.component.html @@ -82,6 +82,18 @@ +
+ + + +
+
diff --git a/projects/ledge-render/src/lib/ledge-render.component.ts b/projects/ledge-render/src/lib/ledge-render.component.ts index 8249b7a6..0c61bd06 100644 --- a/projects/ledge-render/src/lib/ledge-render.component.ts +++ b/projects/ledge-render/src/lib/ledge-render.component.ts @@ -5,16 +5,16 @@ import { Input, OnChanges, OnInit, - SimpleChanges -} from '@angular/core'; -import { Token, Tokens, TokensList } from 'marked'; -import marked, { Slugger } from 'marked/lib/marked'; -import LedgeMarkdownConverter from './components/model/ledge-markdown-converter'; + SimpleChanges, +} from "@angular/core"; +import { Token, Tokens, TokensList } from "marked"; +import marked, { Slugger } from "marked/lib/marked"; +import LedgeMarkdownConverter from "./components/model/ledge-markdown-converter"; @Component({ - selector: 'ledge-render', - templateUrl: './ledge-render.component.html', - styleUrls: ['./ledge-render.component.scss'], + selector: "ledge-render", + templateUrl: "./ledge-render.component.html", + styleUrls: ["./ledge-render.component.scss"], changeDetection: ChangeDetectionStrategy.OnPush, }) export class LedgeRenderComponent implements OnInit, AfterViewInit, OnChanges { @@ -64,8 +64,8 @@ export class LedgeRenderComponent implements OnInit, AfterViewInit, OnChanges { private parseText() { let body = this.token.text; - while (this.peek().type === 'text') { - body += '\n' + (this.next() as any).text; + while (this.peek().type === "text") { + body += "\n" + (this.next() as any).text; } return body; @@ -75,71 +75,71 @@ export class LedgeRenderComponent implements OnInit, AfterViewInit, OnChanges { const unescapeTest = /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/gi; return html.replace(unescapeTest, (_, n) => { n = n.toLowerCase(); - if (n === 'colon') { - return ':'; + if (n === "colon") { + return ":"; } - if (n.charAt(0) === '#') { - return n.charAt(1) === 'x' + if (n.charAt(0) === "#") { + return n.charAt(1) === "x" ? String.fromCharCode(parseInt(n.substring(2), 16)) : String.fromCharCode(+n.substring(1)); } - return ''; + return ""; }); } private tok() { const token: Token = this.token; switch (token.type) { - case 'table': + case "table": this.markdownData.push(token); break; - case 'code': + case "code": this.handleCode(token); break; - case 'space': - return ''; - case 'blockquote_start': - let body = ''; + case "space": + return ""; + case "blockquote_start": + let body = ""; this.isPureParagraph = false; - while (this.next().type !== 'blockquote_end') { + while (this.next().type !== "blockquote_end") { body += this.tok(); } this.isPureParagraph = true; - this.markdownData.push({ type: 'blockquote', text: body }); + this.markdownData.push({ type: "blockquote", text: body }); break; - case 'paragraph': + case "paragraph": return this.handleParaGraph(token); - case 'text': + case "text": return token.text; - case 'heading': + case "heading": const inline = marked.inlineLexer(token.text, this.tokens.links); this.markdownData.push({ - type: 'heading', + type: "heading", depth: token.depth, text: inline, anchor: this.sluger.slug(this.unescape(inline)), }); break; - case 'list_start': { + case "list_start": { const listBody = []; const ordered = this.token.ordered; const start = this.token.start; this.listQueue.push(1); - while (this.next().type !== 'list_end') { + while (this.next().type !== "list_end") { listBody.push(this.tok()); } this.listQueue.pop(); if (this.listQueue.length === 0) { - this.markdownData.push({ type: 'list', data: listBody, ordered }); + this.markdownData.push({ type: "list", data: listBody, ordered }); } return { children: listBody, ordered, start }; } - case 'list_item_start': { + case "list_item_start": { const itemBody = { - name: '', + name: "", children: [], }; const loose = this.token.loose; @@ -162,8 +162,8 @@ export class LedgeRenderComponent implements OnInit, AfterViewInit, OnChanges { // } // } - while (this.next().type !== 'list_item_end') { - if (!loose && this.token.type === 'text') { + while (this.next().type !== "list_item_end") { + if (!loose && this.token.type === "text") { itemBody.name += marked.inlineLexer( this.parseText(), this.tokens.links @@ -175,10 +175,10 @@ export class LedgeRenderComponent implements OnInit, AfterViewInit, OnChanges { return { body: itemBody, task, checked }; } - case 'hr': + case "hr": this.markdownData.push(token); break; - case 'html': + case "html": return token.text; default: this.markdownData.push(token); @@ -190,7 +190,7 @@ export class LedgeRenderComponent implements OnInit, AfterViewInit, OnChanges { const inline = marked.inlineLexer(token.text, this.tokens.links); if (this.isPureParagraph) { this.markdownData.push({ - type: 'paragraph', + type: "paragraph", data: inline, }); } @@ -201,65 +201,74 @@ export class LedgeRenderComponent implements OnInit, AfterViewInit, OnChanges { private handleCode(token: marked.Tokens.Code) { const codeBlock = token as Tokens.Code; switch (codeBlock.lang) { - case 'chart': + case "chart": const chartData = LedgeMarkdownConverter.toJson(codeBlock.text); - this.markdownData.push({ type: 'chart', data: chartData.tables[0] }); + this.markdownData.push({ type: "chart", data: chartData.tables[0] }); break; - case 'process-step': + case "process-step": const stepData = LedgeMarkdownConverter.toJson(codeBlock.text); this.markdownData.push({ - type: 'process-step', + type: "process-step", data: stepData.lists[0], }); break; - case 'process-table': + case "process-table": const tableData = LedgeMarkdownConverter.toJson(codeBlock.text); this.markdownData.push({ - type: 'process-table', + type: "process-table", data: tableData.tables[0], }); break; - case 'mindmap': + case "process-card": + const cardData = LedgeMarkdownConverter.toJson(codeBlock.text); + this.markdownData.push({ + type: "process-card", + data: cardData.tables[0], + colors: cardData.config.colors || [], + }); + console.log(this.markdownData); + break; + case "mindmap": const mindmapData = LedgeMarkdownConverter.toJson(codeBlock.text); - this.markdownData.push({ type: 'mindmap', data: mindmapData.lists[0] }); + this.markdownData.push({ type: "mindmap", data: mindmapData.lists[0] }); break; - case 'pyramid': + case "pyramid": const pyramidData = LedgeMarkdownConverter.toJson(codeBlock.text); - this.markdownData.push({ type: 'pyramid', data: pyramidData.lists[0] }); + this.markdownData.push({ type: "pyramid", data: pyramidData.lists[0] }); break; - case 'radar': + case "radar": const radarData = LedgeMarkdownConverter.toJson(codeBlock.text); this.markdownData.push({ - type: 'radar', + type: "radar", data: radarData.lists[0], config: radarData.config, }); break; - case 'quadrant': + case "quadrant": const quadrantData = LedgeMarkdownConverter.toJson(codeBlock.text); this.markdownData.push({ - type: 'quadrant', + type: "quadrant", data: quadrantData.lists[0], }); break; - case 'toolset': + case "toolset": const json = LedgeMarkdownConverter.toJson(codeBlock.text); const toolType = json.config.type; this.markdownData.push({ - type: 'toolset', + type: "toolset", data: { type: toolType, data: this.getDataByType(json, toolType) }, }); break; - case 'graphviz': - this.markdownData.push({ type: 'graphviz', data: codeBlock.text }); + case "graphviz": + this.markdownData.push({ type: "graphviz", data: codeBlock.text }); break; - case 'echarts': - this.markdownData.push({ type: 'echarts', data: codeBlock.text }); + case "echarts": + this.markdownData.push({ type: "echarts", data: codeBlock.text }); break; - case 'list-style': + case "list-style": const listData = LedgeMarkdownConverter.toJson(codeBlock.text); this.markdownData.push({ - type: 'list-style', + type: "list-style", data: listData.lists[0].children, config: listData.config, }); @@ -275,9 +284,9 @@ export class LedgeRenderComponent implements OnInit, AfterViewInit, OnChanges { type: any ) { switch (type) { - case 'slider': + case "slider": return json.lists[0].children; - case 'line-chart': + case "line-chart": return json.tables[0]; default: return json; diff --git a/projects/ledge-render/src/lib/ledge-render.module.ts b/projects/ledge-render/src/lib/ledge-render.module.ts index 5e4137b9..7bb1fb82 100644 --- a/projects/ledge-render/src/lib/ledge-render.module.ts +++ b/projects/ledge-render/src/lib/ledge-render.module.ts @@ -11,6 +11,7 @@ import { LedgeRadarComponent } from './chart/ledge-radar/ledge-radar.component'; import { CustomMaterialModule } from './custom-material.module'; import { LedgeRenderComponent } from './ledge-render.component'; import { ToolsetComponent } from './toolset/toolset.component'; +import { SkillCardComponent } from './components/ledge-card/ledge-card.component'; const LedgeComponents = [ LedgeRenderComponent, @@ -21,8 +22,8 @@ const LedgeComponents = [ LedgeQuadrantComponent, LedgeGraphvizComponent, LedgePureEchartsComponent, - ToolsetComponent, + SkillCardComponent, ]; diff --git a/src/app/presentation/home/home.component.html b/src/app/presentation/home/home.component.html index 8398eaaa..50e2ae33 100644 --- a/src/app/presentation/home/home.component.html +++ b/src/app/presentation/home/home.component.html @@ -25,9 +25,13 @@

从而根据不同的企业情况,搭建出专属的 DevOps 流水线

-
-

它可以帮助您寻找最适合的软件工程技术实践

- +
+
「它可以」
+
- 帮助您寻找最适合的软件工程技术实践 -
+
示例:质量内建
+
+ +
@@ -38,7 +42,7 @@

沉淀我们的各种实践,向您提供全程的数据化 ESP Modeling

-
+
Core Contributors
diff --git a/src/app/presentation/home/home.component.scss b/src/app/presentation/home/home.component.scss index 878cb492..33e2d351 100644 --- a/src/app/presentation/home/home.component.scss +++ b/src/app/presentation/home/home.component.scss @@ -46,7 +46,8 @@ .period-title { margin: 0; - h2, h4 { + h2, + h4 { text-align: center; margin: 1em auto 0; } @@ -78,12 +79,10 @@ text-align: center; } - .home-section { width: 1200px; margin: 0 auto; border-radius: 8px; - box-shadow: 0 8px 20px 0 rgba(0, 0, 0, 0.1); background-color: $white; .section-title { @@ -91,8 +90,28 @@ letter-spacing: 2.5px; padding: 36px 0; text-align: center; + font-weight: 600; + } + .section-sub-title { + text-align: center; + font-size: 20px; + font-weight: 600; + letter-spacing: 1.25px; + } + .sample-title { + font-size: 16px; + line-height: 1.5; + letter-spacing: 1px; + text-align: center; + margin-top: 16px; + } + .section-content { + padding-bottom: 60px; } } +.box-shadow { + box-shadow: 0 8px 20px 0 rgba(0, 0, 0, 0.1); +} .contributors { display: flex; @@ -131,7 +150,7 @@ } .work { - font-size: 1.0em; + font-size: 1em; padding: 6px; color: $black; line-height: 1.5; diff --git a/src/assets/docs/home.md b/src/assets/docs/home.md index e2221d3c..9f440947 100644 --- a/src/assets/docs/home.md +++ b/src/assets/docs/home.md @@ -1,12 +1,14 @@ -#### 示例:质量内建 + -```process-table +```process-card | 需求分析 | 开发前 | 开发 | 开发完成 | 测试| 发布前|已发布 | |--|--|--|--|--|--|--| | 用户故事评审 | 特性启动 | 单元测试 | 用户故事验收 | 用户故事测试 | 回归测试 | 监控 | | 估算 | 测试用例设计 | 组件测试 | 底层测试评审 | 探索式测试 | 发布指南 | 支持 | | 方案设计 | 用户故事启动 | | 发布可测试版本 | 缺陷管理 | 用户验收测试 | 质量分析 | -| 迭代计划 | 测试计划 | | | 风险评估 | 发布版本确认 | | -| | | | | 集成测试 | | | -| | | | | 端到端测试 | | | +| 迭代计划 | 测试计划 | | | 风险评估 | 发布版本确认 | | +| | | | | 集成测试 | | | +| | | | | 端到端测试 | | | + +config: {"colors": [{"bg":"#e55852","font":"#b71a09"},{"bg":"#e98832","font":"#c85113"},{"bg":"#f0d668","font":"#b88d0f"},{"bg":"#a4c9cf","font":"#598893"},{"bg":"#47c0af","font":"#175a54"},{"bg":"#387fd5","font":"#9ac9f5"},{"bg":"#7753df","font":"#cbb5f8"}]} ```