├── .editorconfig ├── .gitignore ├── .vscode ├── launch.json └── settings.json ├── LICENSE ├── README.md ├── config ├── github-deploy │ └── index.js ├── head-config.common.js ├── helpers.js ├── html-elements-plugin │ └── index.js ├── karma.conf.js ├── modules │ └── angular2-hmr-prod.js ├── protractor.conf.js ├── spec-bundle.js ├── webpack.common.js ├── webpack.dev.js ├── webpack.github-deploy.js ├── webpack.prod.js └── webpack.test.js ├── e2e ├── app.e2e-spec.ts ├── app.po.ts └── tsconfig.json ├── jsconfig.json ├── karma.conf.js ├── npm-shrinkwrap.json ├── package.json ├── protractor.conf.js ├── public ├── .gitignore └── .npmignore ├── src ├── app │ ├── _shared │ │ ├── _images │ │ │ ├── angular.svg │ │ │ ├── avatar.png │ │ │ └── icons │ │ │ │ ├── camera.svg │ │ │ │ ├── chevron-right.svg │ │ │ │ └── external.svg │ │ ├── _shared.module.ts │ │ ├── api │ │ │ ├── articles │ │ │ │ ├── 00.开篇寄语:Angular —— 王者归来 │ │ │ │ │ ├── _index.md │ │ │ │ │ ├── trends.png │ │ │ │ │ └── wechat.jpg │ │ │ │ ├── 10.我为什么选择Angular 2 │ │ │ │ │ ├── _index.md │ │ │ │ │ ├── architecture.png │ │ │ │ │ ├── background.jpg │ │ │ │ │ ├── dependency-hell.png │ │ │ │ │ ├── high-speed.png │ │ │ │ │ ├── ikea.jpg │ │ │ │ │ ├── level-up.png │ │ │ │ │ ├── level-up.svg │ │ │ │ │ ├── life-cycle.gif │ │ │ │ │ ├── shortcut.jpg │ │ │ │ │ ├── upgrade.jpg │ │ │ │ │ └── w3c.png │ │ │ │ ├── 100.Angular 2的大小与性能 │ │ │ │ │ └── _index.md │ │ │ │ ├── 110.如何理解RxJS │ │ │ │ │ └── _index.md │ │ │ │ ├── 120.Angular 2 中的 Free Style Selector │ │ │ │ │ └── _index.md │ │ │ │ ├── 130.Angular 2中的路由 │ │ │ │ │ └── _index.md │ │ │ │ ├── 140.调查结果与后续计划 │ │ │ │ │ ├── _images │ │ │ │ │ │ ├── group.png │ │ │ │ │ │ ├── logo.png │ │ │ │ │ │ ├── q1.png │ │ │ │ │ │ ├── q2.png │ │ │ │ │ │ ├── q3.png │ │ │ │ │ │ ├── q4.png │ │ │ │ │ │ ├── q5.png │ │ │ │ │ │ ├── q6.png │ │ │ │ │ │ ├── q7.png │ │ │ │ │ │ ├── q8.png │ │ │ │ │ │ └── q9.png │ │ │ │ │ └── _index.md │ │ │ │ ├── 150.流言终结者!Angular的版本与发布 │ │ │ │ │ ├── _index.md │ │ │ │ │ ├── cycle.png │ │ │ │ │ ├── logo.png │ │ │ │ │ ├── schedule.png │ │ │ │ │ └── wechat.jpg │ │ │ │ ├── 160.AngularConnect 2016视频 │ │ │ │ │ ├── _index.md │ │ │ │ │ ├── logo.png │ │ │ │ │ └── sub-group.png │ │ │ │ ├── 161.TypeScript的新特性 │ │ │ │ │ └── _index.md │ │ │ │ ├── 170.Angular依赖注入机制与服务的作用范围 │ │ │ │ │ ├── _index.md │ │ │ │ │ ├── eager-load-module.png │ │ │ │ │ ├── lazy-load.png │ │ │ │ │ └── logo.png │ │ │ │ ├── 180.注解与装饰器的点点滴滴 │ │ │ │ │ ├── _index.md │ │ │ │ │ └── logo.png │ │ │ │ ├── 190.杂谈:何不食肉糜? │ │ │ │ │ ├── _readme.md │ │ │ │ │ └── logo.png │ │ │ │ ├── 20.漫漫升级路……竟然这么简单 │ │ │ │ │ ├── _index.md │ │ │ │ │ ├── bagua.png │ │ │ │ │ ├── new.jpg │ │ │ │ │ ├── running.jpg │ │ │ │ │ ├── start.jpg │ │ │ │ │ └── upgrade.jpg │ │ │ │ ├── 200.如何选择合适的框架 │ │ │ │ │ ├── _readme.md │ │ │ │ │ └── logo.png │ │ │ │ ├── 210.杂谈:君子不器 │ │ │ │ │ ├── _readme.md │ │ │ │ │ └── logo.png │ │ │ │ ├── 220.Angular 2官方文档导读 │ │ │ │ │ └── _index.md │ │ │ │ ├── 230.如何工程化开发大型angular2项目 │ │ │ │ │ ├── _index.md │ │ │ │ │ └── git.png │ │ │ │ ├── 231.如何工程化开发大型angular2项目(上篇续) │ │ │ │ │ ├── _index.md │ │ │ │ │ └── pic.png │ │ │ │ ├── 250.RxJS Overview阅读笔记 │ │ │ │ │ └── _index.md │ │ │ │ ├── 250.一个依赖注入小框架的实现 │ │ │ │ │ └── _index.md │ │ │ │ ├── 250.依赖注入简介 │ │ │ │ │ └── _index.md │ │ │ │ ├── 260.从ng1到ng2的平滑升级[1] │ │ │ │ │ └── _index.md │ │ │ │ ├── 270.从ng1到ng2的平滑升级[2] │ │ │ │ │ └── _index.md │ │ │ │ ├── 270.构建流式应用—RxJS详解 │ │ │ │ │ └── _index.md │ │ │ │ ├── 280.Angular2中的通信方式 │ │ │ │ │ └── _index.md │ │ │ │ ├── 280.如何优雅升级ng2小版本 │ │ │ │ │ └── _index.md │ │ │ │ ├── 290.Angular 2 中的 Structural Directive │ │ │ │ │ ├── _index.md │ │ │ │ │ └── ng_probe.png │ │ │ │ ├── 30.一括抵千言……Angular 2中的绑定 │ │ │ │ │ └── _index.md │ │ │ │ ├── 300.单例模式与Angular │ │ │ │ │ └── _index.md │ │ │ │ ├── 310.GDD大会Angular2优秀项目案例-任意门 │ │ │ │ │ ├── _index.md │ │ │ │ │ └── chat.jpg │ │ │ │ ├── 310.ng-container introduction │ │ │ │ │ └── _index.md │ │ │ │ ├── 320.Angular 2 中的编译器与预编译(AoT)优化 │ │ │ │ │ ├── _index.md │ │ │ │ │ ├── aot-rendering.png │ │ │ │ │ ├── aot.png │ │ │ │ │ ├── jit-rendering.png │ │ │ │ │ └── jit.png │ │ │ │ ├── 40.组件与指令概述 │ │ │ │ │ └── _index.md │ │ │ │ ├── 50.弯道超车!后端程序员的Angular快速指南 │ │ │ │ │ ├── _index.md │ │ │ │ │ ├── angular-1.png │ │ │ │ │ ├── angular-2.svg │ │ │ │ │ ├── competition.jpg │ │ │ │ │ ├── origin.jpg │ │ │ │ │ ├── team.jpg │ │ │ │ │ └── title.jpg │ │ │ │ ├── 60.表单的救赎 │ │ │ │ │ └── _index.md │ │ │ │ ├── 70.Angular 2技术选型指南 │ │ │ │ │ ├── _index.md │ │ │ │ │ └── trends.png │ │ │ │ ├── 80.Angular 2的入门路径 │ │ │ │ │ └── _index.md │ │ │ │ ├── 80.Angular 和 TypeScript 是否为最佳实践? │ │ │ │ │ └── _index.md │ │ │ │ ├── 90.浅谈微信小程序与PWA │ │ │ │ │ ├── 01_PWA_start.png │ │ │ │ │ ├── 02_PWA_prompt.png │ │ │ │ │ ├── 03_PWA_accept.png │ │ │ │ │ ├── 04_PWA_homescreen.png │ │ │ │ │ ├── 05_PWA_launched.png │ │ │ │ │ ├── 06_PWA_launcher.png │ │ │ │ │ └── _index.md │ │ │ │ ├── index.ts │ │ │ │ └── timliu │ │ │ │ │ ├── a-simple-rxjs-test-spec │ │ │ │ │ └── _index.md │ │ │ │ │ ├── angular-versioning │ │ │ │ │ ├── _index.md │ │ │ │ │ ├── angular-releases.png │ │ │ │ │ ├── angular2-versions.png │ │ │ │ │ ├── angular4-tentativeschedule.png │ │ │ │ │ └── semver.png │ │ │ │ │ ├── mock-redux-with-rxjs-episode-2-todo-app │ │ │ │ │ └── _index.md │ │ │ │ │ ├── mock-redux-with-rxjs │ │ │ │ │ └── _index.md │ │ │ │ │ ├── simple-accordion │ │ │ │ │ ├── _index.md │ │ │ │ │ └── screen-shot.png │ │ │ │ │ ├── simple-hmr │ │ │ │ │ └── _index.md │ │ │ │ │ ├── simple-javascript-event-loop-and-async │ │ │ │ │ ├── _index.md │ │ │ │ │ ├── after-enter.png │ │ │ │ │ ├── after-line3.png │ │ │ │ │ └── async-checkbox.png │ │ │ │ │ ├── simple-mutability │ │ │ │ │ └── _index.md │ │ │ │ │ ├── simple-prototype-chain │ │ │ │ │ └── _index.md │ │ │ │ │ └── simple-rxjs │ │ │ │ │ └── _index.md │ │ │ ├── authors │ │ │ │ ├── 10.雪狼.md │ │ │ │ ├── 20.余泽江.md │ │ │ │ ├── 20.袁志.md │ │ │ │ ├── 250.丁乐华.md │ │ │ │ ├── 260.王開寧.md │ │ │ │ ├── 270.木丁糖.md │ │ │ │ ├── 280.易sense.md │ │ │ │ ├── 66.王传业.md │ │ │ │ ├── 67.大炮.md │ │ │ │ ├── Tim刘.md │ │ │ │ ├── VTHINKXIE.md │ │ │ │ ├── _images │ │ │ │ │ ├── 250.丁乐华.jpg │ │ │ │ │ ├── 260.王開寧.jpg │ │ │ │ │ ├── Tim刘.png │ │ │ │ │ ├── VTHINKXIE.jpg │ │ │ │ │ ├── 余泽江.jpg │ │ │ │ │ ├── 易sense.jpg │ │ │ │ │ ├── 木丁糖.jpg │ │ │ │ │ ├── 王传业.jpg │ │ │ │ │ ├── 袁志.jpg │ │ │ │ │ └── 雪狼.jpg │ │ │ │ └── index.ts │ │ │ ├── books │ │ │ │ ├── AngularJS深度剖析与最佳实践 │ │ │ │ │ ├── _index.md │ │ │ │ │ └── cover.jpg │ │ │ │ ├── index.ts │ │ │ │ └── ng-book2 │ │ │ │ │ ├── _index.md │ │ │ │ │ └── cover.png │ │ │ ├── columns │ │ │ │ ├── _images │ │ │ │ │ ├── snowwolf.jpg │ │ │ │ │ └── trotyl.jpg │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── news │ │ │ │ ├── 10.Angular 2 Final即将到来 │ │ │ │ │ ├── _index.md │ │ │ │ │ └── final.svg │ │ │ │ ├── 20.Angular 2正式发布 │ │ │ │ │ ├── _index.md │ │ │ │ │ └── homepage.png │ │ │ │ └── index.ts │ │ │ ├── partners │ │ │ │ ├── _images │ │ │ │ │ ├── angular.svg │ │ │ │ │ └── tw-insights.jpg │ │ │ │ └── index.ts │ │ │ ├── resources │ │ │ │ ├── 10.prime-ng │ │ │ │ │ ├── _index.md │ │ │ │ │ └── logo.svg │ │ │ │ ├── 20.fuel-ui │ │ │ │ │ ├── _index.md │ │ │ │ │ └── logo.png │ │ │ │ ├── 30.awesome │ │ │ │ │ ├── _index.md │ │ │ │ │ ├── badge.svg │ │ │ │ │ └── logo.png │ │ │ │ └── index.ts │ │ │ ├── showcases │ │ │ │ ├── 10.ifish简介 │ │ │ │ │ ├── _images │ │ │ │ │ │ └── ifish.svg │ │ │ │ │ └── _index.md │ │ │ │ ├── 20.Angular BBS简介 │ │ │ │ │ ├── _index.md │ │ │ │ │ └── logo.svg │ │ │ │ └── index.ts │ │ │ └── threads │ │ │ │ ├── 10.欢迎您!陌生的旅者.md │ │ │ │ ├── 20.悬赏!哥德巴赫猜想.md │ │ │ │ ├── 30.Angular 2路由问题.md │ │ │ │ ├── _images │ │ │ │ └── wizard.svg │ │ │ │ └── index.ts │ │ ├── components │ │ │ ├── base │ │ │ │ └── page.component.ts │ │ │ ├── html │ │ │ │ ├── viewer.component.html │ │ │ │ ├── viewer.component.scss │ │ │ │ └── viewer.component.ts │ │ │ ├── index.ts │ │ │ ├── layout │ │ │ │ ├── nav.component.html │ │ │ │ ├── nav.component.scss │ │ │ │ └── nav.component.ts │ │ │ └── menu │ │ │ │ ├── list.component.html │ │ │ │ ├── list.component.scss │ │ │ │ └── list.component.ts │ │ ├── index.ts │ │ ├── models │ │ │ ├── article.ts │ │ │ ├── author.ts │ │ │ ├── book.ts │ │ │ ├── column.ts │ │ │ ├── index.ts │ │ │ ├── link.ts │ │ │ ├── menu-item.ts │ │ │ ├── partner.ts │ │ │ ├── showcase.ts │ │ │ └── thread.ts │ │ ├── operators │ │ │ ├── index.ts │ │ │ └── match-by-id.ts │ │ ├── pipes │ │ │ ├── index.ts │ │ │ └── trust-as-img-url.ts │ │ ├── services │ │ │ ├── auth.ts │ │ │ ├── change-title.ts │ │ │ └── index.ts │ │ ├── styles │ │ │ ├── _app.scss │ │ │ ├── _bootstrap-extends.scss │ │ │ ├── _bootstrap.scss │ │ │ ├── _common.scss │ │ │ ├── _material.scss │ │ │ ├── _mixins.scss │ │ │ └── _variables.scss │ │ └── utils │ │ │ └── index.ts │ ├── about │ │ ├── _README.md │ │ ├── _about-routing.module.ts │ │ ├── _about.module.ts │ │ ├── _images │ │ │ ├── about.svg │ │ │ ├── angular.svg │ │ │ ├── books.svg │ │ │ ├── chevron-right.svg │ │ │ ├── handshake.svg │ │ │ └── showcase.svg │ │ ├── book │ │ │ ├── _README.md │ │ │ ├── details.component.html │ │ │ ├── details.component.scss │ │ │ ├── details.component.ts │ │ │ ├── home.component.html │ │ │ ├── home.component.scss │ │ │ ├── home.component.ts │ │ │ ├── index.ts │ │ │ ├── list.component.html │ │ │ ├── list.component.scss │ │ │ ├── list.component.ts │ │ │ ├── show.component.html │ │ │ ├── show.component.scss │ │ │ └── show.component.ts │ │ ├── home.component.html │ │ ├── home.component.scss │ │ ├── home.component.ts │ │ ├── index.ts │ │ ├── join.component.html │ │ ├── join.component.scss │ │ ├── join.component.ts │ │ ├── showcase │ │ │ ├── _README.md │ │ │ ├── details.component.html │ │ │ ├── details.component.scss │ │ │ ├── details.component.ts │ │ │ ├── home.component.html │ │ │ ├── home.component.scss │ │ │ ├── home.component.ts │ │ │ ├── index.ts │ │ │ ├── list.component.html │ │ │ ├── list.component.scss │ │ │ ├── list.component.ts │ │ │ ├── show.component.html │ │ │ ├── show.component.scss │ │ │ └── show.component.ts │ │ ├── site.component.jade │ │ ├── site.component.scss │ │ ├── site.component.ts │ │ ├── us.component.html │ │ ├── us.component.scss │ │ └── us.component.ts │ ├── app-routing.module.ts │ ├── app.component.html │ ├── app.component.scss │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.module.ts │ ├── bbs │ │ ├── _bbs-routing.module.ts │ │ ├── _bbs.module.ts │ │ ├── _images │ │ │ └── ask.svg │ │ ├── home.component.html │ │ ├── home.component.scss │ │ ├── home.component.ts │ │ ├── index.ts │ │ └── thread │ │ │ ├── _README.md │ │ │ ├── _images │ │ │ ├── add.svg │ │ │ └── ask.svg │ │ │ ├── create.component.html │ │ │ ├── create.component.scss │ │ │ ├── create.component.ts │ │ │ ├── details.component.html │ │ │ ├── details.component.scss │ │ │ ├── details.component.ts │ │ │ ├── home.component.html │ │ │ ├── home.component.scss │ │ │ ├── home.component.ts │ │ │ ├── index.ts │ │ │ ├── list.component.html │ │ │ ├── list.component.scss │ │ │ ├── list.component.ts │ │ │ ├── nav.component.html │ │ │ ├── nav.component.scss │ │ │ ├── nav.component.ts │ │ │ ├── show.component.html │ │ │ ├── show.component.scss │ │ │ └── show.component.ts │ ├── environments │ │ ├── environment.dev.ts │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── index.ts │ ├── lean-ng-module-loader.ts │ ├── library │ │ ├── _README.md │ │ ├── _images │ │ │ ├── articles.svg │ │ │ ├── ask.svg │ │ │ ├── external.svg │ │ │ ├── news.svg │ │ │ ├── professional.svg │ │ │ ├── radar.svg │ │ │ └── wechat.jpg │ │ ├── _library-routing.module.ts │ │ ├── _library.module.ts │ │ ├── article │ │ │ ├── _README.md │ │ │ ├── _images │ │ │ │ ├── chevron-left.svg │ │ │ │ ├── chevron-right.svg │ │ │ │ └── devrel.png │ │ │ ├── details.component.html │ │ │ ├── details.component.scss │ │ │ ├── details.component.ts │ │ │ ├── home.component.html │ │ │ ├── home.component.scss │ │ │ ├── home.component.ts │ │ │ ├── index.ts │ │ │ ├── list.component.html │ │ │ ├── list.component.scss │ │ │ ├── list.component.ts │ │ │ ├── show.component.html │ │ │ ├── show.component.scss │ │ │ └── show.component.ts │ │ ├── author │ │ │ ├── _README.md │ │ │ ├── details.component.html │ │ │ ├── details.component.scss │ │ │ ├── details.component.ts │ │ │ ├── home.component.html │ │ │ ├── home.component.scss │ │ │ ├── home.component.ts │ │ │ ├── index.ts │ │ │ ├── list.component.html │ │ │ ├── list.component.scss │ │ │ ├── list.component.ts │ │ │ ├── show.component.html │ │ │ ├── show.component.scss │ │ │ └── show.component.ts │ │ ├── column │ │ │ ├── _README.md │ │ │ ├── details.component.html │ │ │ ├── details.component.scss │ │ │ ├── details.component.ts │ │ │ ├── home.component.html │ │ │ ├── home.component.scss │ │ │ ├── home.component.ts │ │ │ ├── index.ts │ │ │ ├── list.component.html │ │ │ ├── list.component.scss │ │ │ ├── list.component.ts │ │ │ ├── show.component.html │ │ │ ├── show.component.scss │ │ │ └── show.component.ts │ │ ├── home.component.html │ │ ├── home.component.scss │ │ ├── home.component.ts │ │ ├── news │ │ │ ├── _README.md │ │ │ ├── details.component.html │ │ │ ├── details.component.scss │ │ │ ├── details.component.ts │ │ │ ├── home.component.html │ │ │ ├── home.component.scss │ │ │ ├── home.component.ts │ │ │ ├── index.ts │ │ │ ├── list.component.html │ │ │ ├── list.component.scss │ │ │ ├── list.component.ts │ │ │ ├── show.component.html │ │ │ ├── show.component.scss │ │ │ ├── show.component.ts │ │ │ ├── trend.component.html │ │ │ ├── trend.component.scss │ │ │ └── trend.component.ts │ │ ├── partner │ │ │ ├── _README.md │ │ │ ├── details.component.html │ │ │ ├── details.component.scss │ │ │ ├── details.component.ts │ │ │ ├── home.component.html │ │ │ ├── home.component.scss │ │ │ ├── home.component.ts │ │ │ ├── index.ts │ │ │ ├── list.component.html │ │ │ ├── list.component.scss │ │ │ ├── list.component.ts │ │ │ ├── show.component.html │ │ │ ├── show.component.scss │ │ │ └── show.component.ts │ │ └── resource │ │ │ ├── _README.md │ │ │ ├── details.component.html │ │ │ ├── details.component.scss │ │ │ ├── details.component.ts │ │ │ ├── home.component.html │ │ │ ├── home.component.scss │ │ │ ├── home.component.ts │ │ │ ├── index.ts │ │ │ ├── list.component.html │ │ │ ├── list.component.scss │ │ │ ├── list.component.ts │ │ │ ├── show.component.html │ │ │ ├── show.component.scss │ │ │ └── show.component.ts │ ├── not-found │ │ ├── index.ts │ │ └── not-found.component.ts │ └── user │ │ ├── _README.md │ │ ├── _user-routing.module.ts │ │ ├── _user.module.ts │ │ ├── home.component.html │ │ ├── home.component.scss │ │ ├── home.component.ts │ │ ├── index.ts │ │ ├── login.component.html │ │ ├── login.component.scss │ │ └── login.component.ts ├── custom-typings.d.ts ├── favicon.ico ├── index.html ├── main.scss ├── main.ts ├── polyfills.ts ├── test.ts └── vendor.ts ├── tsconfig.json ├── tslint.json ├── typedoc.json ├── webpack.config.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.md] 13 | max_line_length = 0 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | 7 | # dependencies 8 | /node_modules 9 | /bower_components 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | *.launch 16 | .settings/ 17 | 18 | # misc 19 | /.sass-cache 20 | /connect.lock 21 | /coverage/* 22 | /libpeerconnection.log 23 | npm-debug.log 24 | testem.log 25 | /typings 26 | 27 | # e2e 28 | /e2e/*.js 29 | /e2e/*.map 30 | 31 | #System Files 32 | .DS_Store 33 | Thumbs.db 34 | .vscode/chrome 35 | yarn.lock 36 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch Chrome against localhost, with sourcemaps", 6 | "type": "chrome", 7 | "request": "launch", 8 | "url": "http://localhost:3000/", 9 | "runtimeArgs": [ 10 | "--disable-web-security", 11 | "--user-data-dir", 12 | "--remote-debugging-port=9222" 13 | ], 14 | "sourceMaps": true, 15 | "webRoot": "${workspaceRoot}" 16 | }, 17 | { 18 | "name": "Attach to Chrome, with sourcemaps", 19 | "type": "chrome", 20 | "request": "attach", 21 | "url": "http://localhost:3000/", 22 | "port": 9222, 23 | "sourceMaps": true, 24 | "webRoot": "${workspaceRoot}" 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // 将设置放入此文件中以覆盖默认值和用户设置。 2 | { 3 | "typescript.tsdk": "node_modules/typescript/lib/" 4 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2016 angular.cn. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular BBS开发指南 2 | 3 | ## 技术栈 4 | 5 | Angular 2 6 | 7 | ## 环境准备 8 | 9 | 请先安装NodeJS 5+。 10 | 11 | ## 启动 12 | 13 | 进入本目录,运行`npm install`命令。也可以使用[Yarn](https://yarnpkg.com/en/docs/install)来安装。 14 | 15 | 墙速有限或者存在连接问题的同学,可能无法正常使用npm安装依赖包,推荐安装并使用cnpm代替npm,运行以下指令: 16 | `npm i cnpm -g` 17 | `cnpm install` 18 | 19 | 20 | 运行`npm start`命令,启动完成后会在启动一个开发服务器。 21 | 22 | ## 重要!!!投稿指南! 23 | 24 | Angular中文社区热烈欢迎各位投稿。延续程序员的光荣传统,我们使用Github接收稿件! 25 | 26 | 首先,你要会发Pull Request,如果不会用可以参见。 27 | 28 | 然后,请找到`src/app/_shared/api/articles`目录,仿照我已经写的这些文章,把你的文章放进去(用Markdown、Jade、HTML都可以,可以引用图片等),并在index.ts中引用它。 29 | 30 | 然后,请找到`src/app/_shared/api/authors`目录,把你的个人简介(含靓照)放进去,你就是正式的作者了,用户看到你的名字可以点进去查看详情。 31 | 32 | 最后,如果你想创建自己的专栏,请找到`src/app/_shared/api/columns`目录,编辑`index.ts`,添加你的专栏简介。当然,专栏是一种荣誉,专栏的文章有质量和数量的要求,如果你创建了专栏,我以后可能会追着你催稿哦,不过这都是小意思,对吧! 33 | 34 | ## 文章格式注意事项 35 | 36 | 为增加阅读体验,减少运营者的工作,请各位投稿时注意以下事项: 37 | 38 | 1. 文章书写语言markdown,语法参考[这里](https://guides.github.com/features/mastering-markdown/) 39 | 2. pr之后尽量在github自己先view一下,保证格式是自己预期的 40 | 3. markdown中`#`的使用:一个表示文章题目、两个表示一级标题、三个表示二级标题...依次类推。虽然有专门管理文章标题的元数据,建议还是在文章的文件中都添加文章题目 41 | 42 | 示例: 43 | ``` 44 | # 文章题目 45 | 46 | ## 前言 47 | 48 | ## 内容 49 | 50 | ### 内容1 51 | 52 | ### 内容2 53 | 54 | ## 总结 55 | ``` 56 | 4. 代码尽量添加编程语言标识,例如:```` ```js ````(表示代码由js写成) 57 | 5. 每段文字上下都空一行,行首不需要留空格 58 | 6. 不要给标题添加序号 59 | 60 | 示例(不好的): 61 | ``` 62 | ## 一、内容 63 | ### 1. 内容1 64 | ``` 65 | 66 | ## 写文章参考方向 67 | 68 | 大方向:**只要是对用ng2做开发有用的,不一定局限在ng2** 69 | 70 | 具体方向: 71 | 72 | - ng2基本概念的介绍(各个功能的解析、组件、依赖注入、模块化、及其相关的历史、小demo展示某个概念) 73 | - RxJS基本概念的介绍(异步、处理异步的方式、及其相关历史、小demo展示某个概念) 74 | - TypeScript/JavaScript语言相关内容(TS语言的基础知识、TS编译器的使用、浏览器相关、小demo展示等) 75 | - 面向对象/函数式编程相关(模式、优缺点分析、最佳实践) 76 | - 构建工具介绍(如何使用各种构建工具打包、原理是啥、angular-cli、webpack) 77 | - Angular2的change log的实时翻译和解释(新特性) 78 | - 工程化相关的实践(构建、打包、发布、调试) 79 | - 优化实践(懒加载、预加载、体积优化、预编译、服务器端渲染等) 80 | - 新的技术和框架分析 81 | - 前端/全栈协作方式 82 | - 踩的坑及解决方法 83 | - 编程复杂度的处理 84 | -------------------------------------------------------------------------------- /config/github-deploy/index.js: -------------------------------------------------------------------------------- 1 | const helpers = require('../helpers'); 2 | const execSync = require('child_process').execSync; 3 | 4 | const REPO_NAME_RE = /Push {2}URL: https:\/\/github\.com\/.*\/(.*)\.git/; 5 | 6 | function getWebpackConfigModule() { 7 | if (helpers.hasProcessFlag('github-dev')) { 8 | return require('../webpack.dev.js'); 9 | } else if (helpers.hasProcessFlag('github-prod')) { 10 | return require('../webpack.prod.js'); 11 | } else { 12 | throw new Error('Invalid compile option.'); 13 | } 14 | } 15 | 16 | function getRepoName(remoteName) { 17 | remoteName = remoteName || 'origin'; 18 | 19 | var stdout = execSync('git remote show ' + remoteName), 20 | match = REPO_NAME_RE.exec(stdout); 21 | 22 | if (!match) { 23 | throw new Error('Could not find a repository on remote ' + remoteName); 24 | } else { 25 | return match[1]; 26 | } 27 | } 28 | 29 | function stripTrailing(str, char) { 30 | 31 | if (str[0] === char) { 32 | str = str.substr(1); 33 | } 34 | 35 | if (str.substr(-1) === char) { 36 | str = str.substr(0, str.length - 1); 37 | } 38 | 39 | return str; 40 | } 41 | 42 | /** 43 | * Given a string remove trailing slashes and adds 1 slash at the end of the string. 44 | * 45 | * Example: 46 | * safeUrl('/value/') 47 | * // 'value/' 48 | * 49 | * @param url 50 | * @returns {string} 51 | */ 52 | function safeUrl(url) { 53 | const stripped = stripTrailing(url || '', '/'); 54 | return stripped ? stripped + '/' : ''; 55 | } 56 | 57 | exports.getWebpackConfigModule = getWebpackConfigModule; 58 | exports.getRepoName = getRepoName; 59 | exports.safeUrl = safeUrl; 60 | -------------------------------------------------------------------------------- /config/helpers.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @AngularClass 3 | */ 4 | var path = require('path'); 5 | 6 | // Helper functions 7 | var ROOT = path.resolve(__dirname, '..'); 8 | 9 | function hasProcessFlag(flag) { 10 | return process.argv.join('').indexOf(flag) > -1; 11 | } 12 | 13 | function isWebpackDevServer() { 14 | return process.argv[1] && !! (/webpack-dev-server/.exec(process.argv[1])); 15 | } 16 | 17 | function root(args) { 18 | args = Array.prototype.slice.call(arguments, 0); 19 | return path.join.apply(path, [ROOT].concat(args)); 20 | } 21 | 22 | exports.hasProcessFlag = hasProcessFlag; 23 | exports.isWebpackDevServer = isWebpackDevServer; 24 | exports.root = root; 25 | -------------------------------------------------------------------------------- /config/modules/angular2-hmr-prod.js: -------------------------------------------------------------------------------- 1 | exports.HmrState = function() { 2 | 3 | }; 4 | -------------------------------------------------------------------------------- /config/protractor.conf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @AngularClass 3 | */ 4 | 5 | require('ts-node/register'); 6 | var helpers = require('./helpers'); 7 | 8 | exports.config = { 9 | baseUrl: 'http://localhost:3000/', 10 | 11 | // use `npm run e2e` 12 | specs: [ 13 | helpers.root('src/**/**.e2e.ts'), 14 | helpers.root('src/**/*.e2e.ts') 15 | ], 16 | exclude: [], 17 | 18 | framework: 'jasmine2', 19 | 20 | allScriptsTimeout: 110000, 21 | 22 | jasmineNodeOpts: { 23 | showTiming: true, 24 | showColors: true, 25 | isVerbose: false, 26 | includeStackTrace: false, 27 | defaultTimeoutInterval: 400000 28 | }, 29 | directConnect: true, 30 | 31 | capabilities: { 32 | 'browserName': 'chrome', 33 | 'chromeOptions': { 34 | 'args': ['show-fps-counter=true'] 35 | } 36 | }, 37 | 38 | onPrepare: function() { 39 | browser.ignoreSynchronization = true; 40 | }, 41 | 42 | /** 43 | * Angular 2 configuration 44 | * 45 | * useAllAngular2AppRoots: tells Protractor to wait for any angular2 apps on the page instead of just the one matching 46 | * `rootEl` 47 | */ 48 | useAllAngular2AppRoots: true 49 | }; 50 | -------------------------------------------------------------------------------- /e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { UserUiPage } from './app.po'; 2 | 3 | describe('user-ui App', function() { 4 | let page: UserUiPage; 5 | 6 | beforeEach(() => { 7 | page = new UserUiPage(); 8 | }); 9 | 10 | it('should display message saying app works', () => { 11 | page.navigateTo(); 12 | expect(page.getParagraphText()).toEqual('app works!'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /e2e/app.po.ts: -------------------------------------------------------------------------------- 1 | export class UserUiPage { 2 | navigateTo() { 3 | return browser.get('/'); 4 | } 5 | 6 | getParagraphText() { 7 | return element(by.css('app-root h1')).getText(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "declaration": false, 5 | "emitDecoratorMetadata": true, 6 | "experimentalDecorators": true, 7 | "module": "commonjs", 8 | "moduleResolution": "node", 9 | "outDir": "../dist/out-tsc-e2e", 10 | "sourceMap": true, 11 | "target": "es5", 12 | "typeRoots": [ 13 | "../node_modules/@types" 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "allowSyntheticDefaultImports": true 6 | }, 7 | "exclude": [ 8 | "node_modules", 9 | "bower_components", 10 | "jspm_packages", 11 | "tmp", 12 | "temp" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @AngularClass 3 | */ 4 | 5 | // Look in ./config for karma.conf.js 6 | module.exports = require('./config/karma.conf.js'); 7 | -------------------------------------------------------------------------------- /protractor.conf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @AngularClass 3 | * e2e End to End 4 | */ 5 | 6 | // look in ./config for protractor.conf.js 7 | exports.config = require('./config/protractor.conf.js').config; -------------------------------------------------------------------------------- /public/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/public/.gitignore -------------------------------------------------------------------------------- /public/.npmignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/public/.npmignore -------------------------------------------------------------------------------- /src/app/_shared/_images/angular.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/app/_shared/_images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/_images/avatar.png -------------------------------------------------------------------------------- /src/app/_shared/_images/icons/camera.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /src/app/_shared/_images/icons/chevron-right.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /src/app/_shared/_images/icons/external.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /src/app/_shared/_shared.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule, ModuleWithProviders } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { SHARED_APIS } from './api/index'; 4 | import { RouterModule } from '@angular/router'; 5 | import { SHARED_COMPONENTS } from './components/index'; 6 | import { SHARED_PIPES } from './pipes/index'; 7 | import { SHARED_SERVICES } from './services/index'; 8 | 9 | @NgModule({ 10 | imports: [ 11 | CommonModule, 12 | RouterModule, 13 | ], 14 | declarations: [...SHARED_COMPONENTS, ...SHARED_PIPES], 15 | exports: [...SHARED_COMPONENTS, ...SHARED_PIPES], 16 | }) 17 | export default class SharedModule { 18 | static forRoot(): ModuleWithProviders { 19 | return { 20 | ngModule: SharedModule, 21 | providers: [...SHARED_APIS, ...SHARED_SERVICES], 22 | }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/app/_shared/api/articles/00.开篇寄语:Angular —— 王者归来/_index.md: -------------------------------------------------------------------------------- 1 | # 开篇寄语:Angular —— 王者归来! 2 | 3 | ![趋势图](./trends.png) 4 | 来自[Google Trends](https://www.google.com/trends/explore?date=2009-08-09%202016-09-09&q=%2Fm%2F0j45p7w,%2Fm%2F012l1vxv,vuejs,%22Angular%202%22) 5 | 6 | ## 过去 7 | 8 | 一图抵千言。 9 | 10 | 从这张图上可以看出几项前端技术在全球范围内的成长趋势。可以看到Angular 1当年的积累与爆发。 11 | 12 | 不过,这些不是重点,本文要谈论的是这条代表Angular 2的绿线。 13 | 14 | Angular 2从2014年初对外公布开发计划,到现在已经两年半有余。期间,共经历了56个alpha、18个beta、8个rc。相信这样一个巨型开源项目组的倾力奉献有资格承担你的信任与期待! 15 | 16 | ## 现在! 17 | 18 | 发这篇文章,是因为Angular 2的Milestone中已经没有新的RC计划,这意味着Angular的API已经稳定,准备最后发布了。当然,剩下的周边任务还是很多的:修复bug、完善文档、完善生态等等。即使你不是早鸟,现在也应该开始学习它了! 19 | 20 | 可以说这是为现实项目储备Angular 2技能的最佳时机。 21 | 22 | 如果要学习Angular 2,显然,各种学习资源是必不可少的。这里先列出一些参考资料供大家入门: 23 | 24 | ### [英文官网](https://angular.io) 25 | 26 | 如果你英文很好,那么英文官网将是最好的学习资料。显然,作为官方开发组亲自维护的文档站,无论是权威程度还是更新速度,都是最好的。 27 | 28 | ### [中文官网](https://angular.cn) 29 | 30 | 如果你读英文还有困难,那么请访问这个中文官网。这是我和一位留学生朋友对英文官网的翻译版,并得到了官方开发组的承认和推荐。今后一旦官网有更新,我们也会保持同步翻译 —— 虽然这很累,但值得! 31 | 32 | ### [Angular中文社区微信号](https://wx.angular.cn) 33 | 34 | 请识别![二维码](./wechat.jpg)关注我们。从今天起,官方微信号将正式启用,这意味着这里将会频繁发表Angular 2和前端开发的相关文章、新闻等。所有这些文章都会被存档到。 35 | 36 | 同时,Angular中文社区在InfoQ等技术媒体上发表的文章也都会在这里存档。同时,我们的一个问答栏目也在建设中,这是一个基于Github API的手机版开源论坛,争取早日为大家提供服务。 37 | 38 | ### Angular中文社区系列QQ群 39 | 40 | - 278252889( Angular 中文社区,2000人已满) 41 | - 305739270( Angular 中文社区二群,2000人) 42 | - 207542263( Angular 中文社区三群,1000人) 43 | - 200242234( Angular 互助组,500人) 44 | - 110455272( Ionic 开发实践,500人) 45 | 46 | ## 未来! 47 | 48 | 古人云:知易行难。学习Angular 2的最佳方式是实践。除了自己做学习项目之外,也可以学习别人的开源项目,比如是本网站的全套源码,而是一个开源的个人博客项目。 49 | 50 | 不过目前如果你要在实际项目中使用它,还是要慎重一点。 51 | 52 | 首要的障碍在于它不支持IE8,所以如果要继续支持,还是继续使用Angular 1.2吧。 53 | 54 | 其次,它仍然没有Final Release,如果你们团队中没有能坐镇的资深前端,建议还是等两个月再尝试使用它,到时候的社区支持就会完善得多,各种坑也基本上都暴露出来了。 55 | 56 | 最后,先**不要**把既有项目迁移到Angular 2。即使Angular 2提供了相当明确的升级路径,升级也仍然是一个技术活儿,工作量也不小。在你对Angular 2相当熟悉之前,建议只用小规模的新项目进行试点。原有的Angular 1项目最好按照官方提供的最佳实践进行重构,完成重构之后,迁移起来就容易多了。 57 | -------------------------------------------------------------------------------- /src/app/_shared/api/articles/00.开篇寄语:Angular —— 王者归来/trends.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/00.开篇寄语:Angular —— 王者归来/trends.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/00.开篇寄语:Angular —— 王者归来/wechat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/00.开篇寄语:Angular —— 王者归来/wechat.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/articles/10.我为什么选择Angular 2/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/10.我为什么选择Angular 2/architecture.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/10.我为什么选择Angular 2/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/10.我为什么选择Angular 2/background.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/articles/10.我为什么选择Angular 2/dependency-hell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/10.我为什么选择Angular 2/dependency-hell.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/10.我为什么选择Angular 2/high-speed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/10.我为什么选择Angular 2/high-speed.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/10.我为什么选择Angular 2/ikea.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/10.我为什么选择Angular 2/ikea.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/articles/10.我为什么选择Angular 2/level-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/10.我为什么选择Angular 2/level-up.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/10.我为什么选择Angular 2/level-up.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | level-up 6 | Created with Sketch. 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/app/_shared/api/articles/10.我为什么选择Angular 2/life-cycle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/10.我为什么选择Angular 2/life-cycle.gif -------------------------------------------------------------------------------- /src/app/_shared/api/articles/10.我为什么选择Angular 2/shortcut.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/10.我为什么选择Angular 2/shortcut.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/articles/10.我为什么选择Angular 2/upgrade.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/10.我为什么选择Angular 2/upgrade.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/articles/10.我为什么选择Angular 2/w3c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/10.我为什么选择Angular 2/w3c.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/140.调查结果与后续计划/_images/group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/140.调查结果与后续计划/_images/group.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/140.调查结果与后续计划/_images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/140.调查结果与后续计划/_images/logo.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/140.调查结果与后续计划/_images/q1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/140.调查结果与后续计划/_images/q1.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/140.调查结果与后续计划/_images/q2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/140.调查结果与后续计划/_images/q2.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/140.调查结果与后续计划/_images/q3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/140.调查结果与后续计划/_images/q3.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/140.调查结果与后续计划/_images/q4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/140.调查结果与后续计划/_images/q4.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/140.调查结果与后续计划/_images/q5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/140.调查结果与后续计划/_images/q5.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/140.调查结果与后续计划/_images/q6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/140.调查结果与后续计划/_images/q6.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/140.调查结果与后续计划/_images/q7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/140.调查结果与后续计划/_images/q7.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/140.调查结果与后续计划/_images/q8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/140.调查结果与后续计划/_images/q8.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/140.调查结果与后续计划/_images/q9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/140.调查结果与后续计划/_images/q9.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/150.流言终结者!Angular的版本与发布/cycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/150.流言终结者!Angular的版本与发布/cycle.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/150.流言终结者!Angular的版本与发布/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/150.流言终结者!Angular的版本与发布/logo.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/150.流言终结者!Angular的版本与发布/schedule.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/150.流言终结者!Angular的版本与发布/schedule.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/150.流言终结者!Angular的版本与发布/wechat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/150.流言终结者!Angular的版本与发布/wechat.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/articles/160.AngularConnect 2016视频/_index.md: -------------------------------------------------------------------------------- 1 | # Angular Connect 2016 2 | 3 | ![Logo](./logo.png) 4 | 5 | 2016年09月27日和28日,在伦敦召开了欧洲今年最大规模的AngularConnect会议。这次持续两天的大会云集了众多世界顶级Angular专家,特别是来自官方开发组的多位主力成员。 6 | 7 | 会议也给我们带来了很多最新消息和前沿进展。目前官方已经放出了36个官方视频,但都放在YouTube上无法访问。不过别担心,谷歌开发技术推广部已经把这些视频上传到了国内的视频网站,欢迎[点击查看](http://i.youku.com/i/UMjczOTc0NDkzNg==/navcustom?id=507955)。当然,这些视频的字幕都是英文的。我们将在今后逐渐为部分重要的视频配上中文字幕。不过期望值也别太高,我们太忙了,如果你愿意当字幕组的志愿者,可以识别下方的二维码来加入我们的字幕组,我们需要你。请注意,这个字幕组只是用来翻译字幕的,不会解答其它技术问题。 8 | 9 | ![subtitle group](./sub-group.png) 10 | 11 | 我们现在已经完成的是一个视频的中文字幕。注意:视频流量很大,请勿在**4G网络**下观看! 12 | 13 | 翻译:汪志成、叶志敏。 14 | 15 | 时间轴、校对:程路、章小飞 16 | 17 | [移动开发?听我的(Jeff Cross)](http://v.qq.com/x/page/h0336m6rbez.html) 18 | 19 | -------------------------------------------------------------------------------- /src/app/_shared/api/articles/160.AngularConnect 2016视频/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/160.AngularConnect 2016视频/logo.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/160.AngularConnect 2016视频/sub-group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/160.AngularConnect 2016视频/sub-group.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/170.Angular依赖注入机制与服务的作用范围/eager-load-module.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/170.Angular依赖注入机制与服务的作用范围/eager-load-module.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/170.Angular依赖注入机制与服务的作用范围/lazy-load.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/170.Angular依赖注入机制与服务的作用范围/lazy-load.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/170.Angular依赖注入机制与服务的作用范围/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/170.Angular依赖注入机制与服务的作用范围/logo.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/180.注解与装饰器的点点滴滴/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/180.注解与装饰器的点点滴滴/logo.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/190.杂谈:何不食肉糜?/_readme.md: -------------------------------------------------------------------------------- 1 | # 杂谈:何不食肉糜? 2 | 3 | ![儒](./logo.png) 4 | 5 | ## 历史 6 | 7 | 晋朝某年。天下大旱。 8 | 9 | 老百姓没有粮食吃,被迫吃草根、树皮、观音土充饥。饿殍遍地。皇宫中照样歌舞升平。当大臣来报告这场饥荒时,晋惠帝真是为老百姓操碎了心:“老百姓都没有粟米吃了?那岂不是要饿死?”,过了一会儿他又疑惑地问道:“他们虽然没粮食,为什么不吃肉粥呢?” 10 | 11 | 别笑。晋惠帝是认真的。在那个门阀分明的时代,晋惠帝可谓是精英中的精英,顶级精英。然而,他自幼在深宫长大,无法看见寻常人家的生活,无法理解平民的喜怒哀乐,甚至都不知道肉是从哪里来的。 12 | 13 | 不过,把这些归于晋惠帝的“白痴”、“无良”也有失公允。事实上,这是那个时代的常态。语文课上,我们可能学过“王凯与石崇斗富”,这只是晋朝积重难返的一个缩影。其根本原因在于阶层的固化。 14 | 15 | 这种阶层固化不但触发了上层大乱斗,成为八王之乱的主因,更严重的是它撕裂了社会,让晋朝在面对游牧民族入侵时毫无还手之力。底层人民受尽了歧视,因此并不认为这是自己的国家,连一个“岳飞”都不曾出过。孟子曰“君视民如草芥,则民视君如寇仇”。史家称这段悲剧为“五胡乱华”,但我认为其根本原因并不在于“五胡”,而源自当时“精英群体”的自私、自恋与短视。“旧时王谢堂前燕,飞入寻常百姓家”,活该! 16 | 17 | 当社会走向沉沦,没有人能置身事外。中国历史上几乎每个最黑暗的时代都是阶层撕裂最严重的时代。这不是巧合。俗话说“不作不死”,阶层撕裂正是一个民族的典型“作死”行为,无可救药。 18 | 19 | ## 现实 20 | 21 | 也许你自己不觉得,但作为程序员,我们大多数人在全国范围内收入其实已经处于前5%了(因为贫富差距过大)。随着软件技术渗透到社会的每一个角落,我们对社会的影响力也会随之越来越大。只要没有意外,那么我们已经或者迟早都会成为中产阶级。但中产阶级并不只意味着财富,更重要的是道义担当与社会责任。在中国传统文化中,讲究的是:大丈夫立于天地间,“铁肩担道义,妙手著文章”。 22 | 23 | 值得庆幸的是,我们这些人大多是从底层成长起来的,不至于像晋惠帝一样把“何不食肉糜”当做理所当然的事。请让自己和后人始终保持睁开眼睛看世界,而不要成为晋惠帝。 24 | 25 | 我们力量有限,但不等于无能为力。 26 | 27 | 首先,不作恶。假如你为生活所迫,不得不为作恶者工作,请至少提高作恶者的成本 —— 对作恶者,请把你的心理价位提高50%,只要所有程序员都有这个共识,那么就能形成一种事实性的爱心罚款。 28 | 29 | 其次,不要歧视。有很多人因为各种原因而无法得到良好的教育,尽力去帮助他们,而不要鄙视或者认为他们只是不学无术。这世上有很多人因为凑不齐学费而放弃了大学梦。 30 | 31 | 最后,Just do IT。是的,只要合理使用,那么信息技术就能让社会变得更加平等。阶层固化的来源往往是信息不畅,请用你的业余时间,去帮助别人消除各种信息的藩篱。 32 | 而这也是我当初每天花三个小时的业余时间去翻译Angular 2官方文档的根本动力。 33 | 限于英语水平,有很多人(包括我)无法顺畅地通过英文获取最新信息。 34 | 也许有人觉得“活该,谁叫你不好好学英语呢?”,但我鄙视这种“何不食肉糜”的心态。 35 | 我相信:任何人,只要他有梦想,就值得我们去帮助。即使他真的曾经荒废学业,也不应该让这些过往成为他现在被歧视的理由。他会去学英语,但他现在急需一份好工作。 36 | 有人说:种一棵树,最好的时间是十年前,其次,是现在。所以,Just do it!从一点一滴开始,从身边开始,让社会变得更美好,这样我们才能不被阶层撕裂导致的黑暗时代所吞噬。 37 | 38 | 我们都是水滴,但我们有一颗滚滚向前的心。 39 | -------------------------------------------------------------------------------- /src/app/_shared/api/articles/190.杂谈:何不食肉糜?/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/190.杂谈:何不食肉糜?/logo.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/20.漫漫升级路……竟然这么简单/bagua.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/20.漫漫升级路……竟然这么简单/bagua.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/20.漫漫升级路……竟然这么简单/new.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/20.漫漫升级路……竟然这么简单/new.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/articles/20.漫漫升级路……竟然这么简单/running.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/20.漫漫升级路……竟然这么简单/running.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/articles/20.漫漫升级路……竟然这么简单/start.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/20.漫漫升级路……竟然这么简单/start.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/articles/20.漫漫升级路……竟然这么简单/upgrade.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/20.漫漫升级路……竟然这么简单/upgrade.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/articles/200.如何选择合适的框架/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/200.如何选择合适的框架/logo.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/210.杂谈:君子不器/_readme.md: -------------------------------------------------------------------------------- 1 | # 周末杂谈:君子不器 2 | 3 | ![儒](./logo.png) 4 | 5 | 很多程序员会对自己的未来感到困惑,在我十八年的职业生涯中自然也曾想过不止一次。今天的周末杂谈,就和大家谈谈我对这个问题的思考。 6 | 7 | 雪狼言必称孔孟,那么我们就先从《论语》中的一句话开始。 8 | 9 | > 子曰:君子不器 —— 《论语 - 为政》 10 | 11 | 这句话如果直译,那么意思就是“君子不是东西”,呃,好像有点骂人的味道,那就 …… “君子是东西”?咋还是骂人咧! 12 | 13 | 好吧,换回严肃脸。 14 | 15 | 这句话的关键在于这个“器”字。这也是文史界争议比较多的地方。这里我只说一些比较主流的说法。 16 | -------------------------------------------------------------------------------- /src/app/_shared/api/articles/210.杂谈:君子不器/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/210.杂谈:君子不器/logo.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/230.如何工程化开发大型angular2项目/git.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/230.如何工程化开发大型angular2项目/git.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/231.如何工程化开发大型angular2项目(上篇续)/pic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/231.如何工程化开发大型angular2项目(上篇续)/pic.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/250.依赖注入简介/_index.md: -------------------------------------------------------------------------------- 1 | # 依赖注入简介 2 | 3 | 简单来说,依赖注入是一种降低代码之间的耦合度,提高代码的灵活性的编程方法。事情是这样子的: 4 | 5 | 我们编程都是从`Hello World`开始,但它不会永远停留在`Hello World`,它会变得越来越复杂。为了能够掌控程序的复杂,我们引进了模块化。模块化的目的是切分复杂,带来的问题是需要考虑代码之间的合作问题(不只是多人之间的代码,还有自己写的代码之间的合作问题)。合作意味着依赖,比如模块A依赖模块B提供的功能。具体到面向对象编程就是对象A里面,需要使用到对象B的实例。 6 | 7 | 现在问题来了,对象B的实例化是在对象A里面实例化呢,还是先实例化,再将实例化后的实例当参数传给对象A呢?如果实例化的方式不变,当然在对象A里面实例化最好了,因为使用对象A的程序员不需要关注对象A还依赖了对象B。可是呢,需求总是在变化。如果哪天对象B改变了,它在实例化的时候要求添加一个参数,这下对象A就傻了。因为需要将对象B实例化的代码做更改,这相当于A限制了B的改变(不能只修改B,还要考虑到A)。 8 | 9 | 那就选择将对象B的实例当参数传给对象A吧(解决问题的一种方法),这样对象A就不需要知道对象B是如何实例化的了(**题外话,对象B依然需要保证提供的服务方式不变或者说暴露的接口不变**)。这种将依赖的引入从使用者的代码中分离出来,交由框架管理的技术叫做**控制反转**(Inversion of Control)。OK,这里有两种方式将对象B的实例传给对象A。一种是对象A先声明依赖了哪些对象,框架根据声明去实例化这些对象并传给A。另外一种是对象A在需要的时候自己去问框架,框架返回A所依赖的对象B的实例。 10 | 11 | 这两种方式都是**把对象的实例化的问题交由一个依赖管理框架**。第一种方式叫**依赖注入**(Dependency Injection),第二种方式叫**依赖查找**(Dependency Lookup)。这两者的区别在于框架把依赖注入给对象,还是对象主动查找需要的依赖。 12 | 13 | 不管用没用控制反转,代码需要做的事情是一样都不少,控制反转只是将这种实例化的工作交给了代码而不是开发者。因为交给了代码来做,与代码的交互只能变得固定了(比如声明依赖的方式)。**使用控制反转的好处是对象B的修改升级只需考虑对象B和依赖框架**。 14 | 15 | ## 参考文章 16 | 17 | 1. 依赖注入([https://github.com/android-cn/blog/tree/master/java/dependency-injection](https://github.com/android-cn/blog/tree/master/java/dependency-injection)) 18 | 2. 控制反转([https://zh.wikipedia.org/wiki/控制反转](https://zh.wikipedia.org/wiki/控制反转)) 19 | -------------------------------------------------------------------------------- /src/app/_shared/api/articles/290.Angular 2 中的 Structural Directive/ng_probe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/290.Angular 2 中的 Structural Directive/ng_probe.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/310.GDD大会Angular2优秀项目案例-任意门/chat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/310.GDD大会Angular2优秀项目案例-任意门/chat.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/articles/320.Angular 2 中的编译器与预编译(AoT)优化/aot-rendering.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/320.Angular 2 中的编译器与预编译(AoT)优化/aot-rendering.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/320.Angular 2 中的编译器与预编译(AoT)优化/aot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/320.Angular 2 中的编译器与预编译(AoT)优化/aot.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/320.Angular 2 中的编译器与预编译(AoT)优化/jit-rendering.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/320.Angular 2 中的编译器与预编译(AoT)优化/jit-rendering.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/320.Angular 2 中的编译器与预编译(AoT)优化/jit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/320.Angular 2 中的编译器与预编译(AoT)优化/jit.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/50.弯道超车!后端程序员的Angular快速指南/angular-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/50.弯道超车!后端程序员的Angular快速指南/angular-1.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/50.弯道超车!后端程序员的Angular快速指南/angular-2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/app/_shared/api/articles/50.弯道超车!后端程序员的Angular快速指南/competition.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/50.弯道超车!后端程序员的Angular快速指南/competition.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/articles/50.弯道超车!后端程序员的Angular快速指南/origin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/50.弯道超车!后端程序员的Angular快速指南/origin.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/articles/50.弯道超车!后端程序员的Angular快速指南/team.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/50.弯道超车!后端程序员的Angular快速指南/team.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/articles/50.弯道超车!后端程序员的Angular快速指南/title.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/50.弯道超车!后端程序员的Angular快速指南/title.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/articles/70.Angular 2技术选型指南/trends.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/70.Angular 2技术选型指南/trends.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/90.浅谈微信小程序与PWA/01_PWA_start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/90.浅谈微信小程序与PWA/01_PWA_start.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/90.浅谈微信小程序与PWA/02_PWA_prompt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/90.浅谈微信小程序与PWA/02_PWA_prompt.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/90.浅谈微信小程序与PWA/03_PWA_accept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/90.浅谈微信小程序与PWA/03_PWA_accept.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/90.浅谈微信小程序与PWA/04_PWA_homescreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/90.浅谈微信小程序与PWA/04_PWA_homescreen.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/90.浅谈微信小程序与PWA/05_PWA_launched.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/90.浅谈微信小程序与PWA/05_PWA_launched.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/90.浅谈微信小程序与PWA/06_PWA_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/90.浅谈微信小程序与PWA/06_PWA_launcher.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/timliu/angular-versioning/angular-releases.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/timliu/angular-versioning/angular-releases.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/timliu/angular-versioning/angular2-versions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/timliu/angular-versioning/angular2-versions.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/timliu/angular-versioning/angular4-tentativeschedule.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/timliu/angular-versioning/angular4-tentativeschedule.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/timliu/angular-versioning/semver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/timliu/angular-versioning/semver.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/timliu/simple-accordion/screen-shot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/timliu/simple-accordion/screen-shot.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/timliu/simple-javascript-event-loop-and-async/after-enter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/timliu/simple-javascript-event-loop-and-async/after-enter.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/timliu/simple-javascript-event-loop-and-async/after-line3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/timliu/simple-javascript-event-loop-and-async/after-line3.png -------------------------------------------------------------------------------- /src/app/_shared/api/articles/timliu/simple-javascript-event-loop-and-async/async-checkbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/articles/timliu/simple-javascript-event-loop-and-async/async-checkbox.png -------------------------------------------------------------------------------- /src/app/_shared/api/authors/10.雪狼.md: -------------------------------------------------------------------------------- 1 | - 专注软件开发十八年 2 | 3 | - 崇尚“简单、专业、分享” 4 | 5 | - 儒学爱好者 & ThoughtWorker 6 | 7 | - Google开发者专家(GDE) 8 | 9 | - 译者之一 10 | 11 | - 《AngularJS深度剖析与最佳实践》 12 | 13 | - Angular中文社区核心成员 -------------------------------------------------------------------------------- /src/app/_shared/api/authors/20.余泽江.md: -------------------------------------------------------------------------------- 1 | No one. 2 | -------------------------------------------------------------------------------- /src/app/_shared/api/authors/20.袁志.md: -------------------------------------------------------------------------------- 1 | - 专注前端开发从业6年 目前27岁 2 | 3 | - 喜欢新技术,热爱编程,对代码的品质有很高的追求 4 | 5 | - 技术栈: node js ts php canvas 6 | 7 | - 目前就职于常州 8 | 9 | - 作为一个大专生,学得电子商务专业,但对编程情有独钟,一步步自学而来,深知其中的坎坷,希望为中国的IT领域献上绵薄之力 10 | 11 | - 开发了不少项目,但是没有什么出名的。不过对MVC 面向对象编程 代码的机构分离构建有着自己的见解。 12 | 13 | - 我也带过不少学生,深知教学不易,这次也是对我的一个全新的挑战。 -------------------------------------------------------------------------------- /src/app/_shared/api/authors/250.丁乐华.md: -------------------------------------------------------------------------------- 1 | - 吭哧吭哧的前端学习者 2 | 3 | - 爱好计算机、经济解释、音乐、徒步 -------------------------------------------------------------------------------- /src/app/_shared/api/authors/260.王開寧.md: -------------------------------------------------------------------------------- 1 | - 任性跳入前端坑,偶尔也涉足一些Java或Node的后端代码 2 | 3 | - [基本不更新的个人主页](http://twincle.github.io/) -------------------------------------------------------------------------------- /src/app/_shared/api/authors/270.木丁糖.md: -------------------------------------------------------------------------------- 1 | - ng爱好者 2 | - Android从业者 -------------------------------------------------------------------------------- /src/app/_shared/api/authors/280.易sense.md: -------------------------------------------------------------------------------- 1 | - angular程序员 2 | 3 | - 前端\摄影\篮球 4 | 5 | - [个人主页](http://www.jianshu.com/users/d0244c5326c5/latest_articles) 6 | -------------------------------------------------------------------------------- /src/app/_shared/api/authors/66.王传业.md: -------------------------------------------------------------------------------- 1 | 2 | module.exports = { 3 | "name" : "王传业" 4 | "nickname" : "indooorsman", 5 | "website" : "https://csser.me", 6 | "github" : "https://github.com/indooorsman", 7 | "about" : `ng粉,2009年开始从事前端开发, 8 | 2012年之前在人人网负责首页、个人主页、新鲜事系统等相关的前端工作, 9 | 后参与三次创业,前端、后端、Android均有涉猎。 10 | 目前在盈科旅游担任前端架构师一职。` 11 | } -------------------------------------------------------------------------------- /src/app/_shared/api/authors/67.大炮.md: -------------------------------------------------------------------------------- 1 | - 一个拉网线专业毕业(通信工程),误打误撞进入前端行业。硬是用硬件编程理解爱上了前端 2 | - 爱好广泛,深度学习,虚拟货币。 3 | - [个人知乎主页](https://www.zhihu.com/people/nong-chao-er-xiao-bin) 4 | -------------------------------------------------------------------------------- /src/app/_shared/api/authors/Tim刘.md: -------------------------------------------------------------------------------- 1 | 翻滚翻滚翻滚 -------------------------------------------------------------------------------- /src/app/_shared/api/authors/VTHINKXIE.md: -------------------------------------------------------------------------------- 1 | -http://weibo.com/vthinkxie 2 | -------------------------------------------------------------------------------- /src/app/_shared/api/authors/_images/250.丁乐华.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/authors/_images/250.丁乐华.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/authors/_images/260.王開寧.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/authors/_images/260.王開寧.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/authors/_images/Tim刘.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/authors/_images/Tim刘.png -------------------------------------------------------------------------------- /src/app/_shared/api/authors/_images/VTHINKXIE.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/authors/_images/VTHINKXIE.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/authors/_images/余泽江.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/authors/_images/余泽江.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/authors/_images/易sense.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/authors/_images/易sense.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/authors/_images/木丁糖.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/authors/_images/木丁糖.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/authors/_images/王传业.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/authors/_images/王传业.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/authors/_images/袁志.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/authors/_images/袁志.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/authors/_images/雪狼.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/authors/_images/雪狼.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/books/AngularJS深度剖析与最佳实践/_index.md: -------------------------------------------------------------------------------- 1 | Angular 1的高级读本,雪狼与破狼的联袂之作。 2 | 3 | 本书是两位一线技术专家的实战经验总结,如果你仍然不得不留在Angular 1,那么本书会帮助你用Angular 2的思想来写Angular 1。 4 | -------------------------------------------------------------------------------- /src/app/_shared/api/books/AngularJS深度剖析与最佳实践/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/books/AngularJS深度剖析与最佳实践/cover.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/books/index.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {Book} from '../../models/book'; 3 | import {Observable} from 'rxjs/Observable'; 4 | import {Link} from '../../models/link'; 5 | const items: Book[] = [ 6 | { 7 | id: 'AngularJS深度剖析与最佳实践', 8 | title: 'AngularJS深度剖析与最佳实践', 9 | picture: require('./AngularJS深度剖析与最佳实践/cover.jpg'), 10 | description: require('./AngularJS深度剖析与最佳实践/_index.md'), 11 | authors: ['雪狼', '破狼', '彭洪伟'], 12 | storeUrls: [ 13 | new Link('http://item.jd.com/11845736.html', '京东商城') 14 | ] 15 | }, 16 | { 17 | id: 'ng-book2', 18 | title: 'Angular 2权威教程', 19 | picture: require('./ng-book2/cover.png'), 20 | description: require('./ng-book2/_index.md'), 21 | authors: ['Ari Lerner', 'Felipe Coury', 'Nate Murray', 'Carlos Taborda'], 22 | translators: ['Angular中文社区'], 23 | storeUrls: [ 24 | new Link('http://www.ituring.com.cn/book/1874', '图灵社区') 25 | ] 26 | }, 27 | ]; 28 | @Injectable() 29 | export class BookApi { 30 | query(): Observable { 31 | return Observable.from(items); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/app/_shared/api/books/ng-book2/_index.md: -------------------------------------------------------------------------------- 1 | “本书堪称Angular 2领域的里程碑式著作,涵盖了关于Angular 2的几乎所有内容。对于没有经验的人,本书平实、通俗的讲解,递进、严密的组织,可以让人毫无压力地登堂入室,迅速领悟新一代Web应用开发的精髓。如果你有相关经验,那本书对Angular 2概念和技术细节的全面剖析,以及引人入胜、切中肯綮的讲解,将帮助你彻底掌握这个框架,在自己职业技术修炼之路上更进一步。” —— 图灵社区 2 | 3 | 作者Ari Lerner是资深全栈工程师,拥有多年AngularJS经验,自办并运营AngularJS电子报ng-newsletter.com,在著名硅谷工程师培训学校Hack Reactor担任AngularJS讲师。FullStack.io创始人。 4 | 5 | 译者是Angular中文社区的九位Angular一线专家。这不是简单的文字翻译,而是在彻底理解原意的基础上进行的重新表述。 6 | 7 | 这是一本“活”书,它从Angular 2的Alpha阶段开始写,随着Angular 2的开发而同步更新,而且今后还将继续保持更新。 8 | 9 | 我们的翻译工作是从RC.4开始的,并且同样保持着同步更新。不过由于我们的译文要出版实体书,因此我们会在作者更新到Angular 2的正式版之后作为内容的截止点。不过可以放心,Angular 2历经两年半的开发之后,到发行正式版时API会完全定型,按照Angular 1的开发记录,即使有新的版本,也只会是功能扩展,API会保持向后兼容的。 10 | 11 | 您的关注是我们的动力!请来[图灵社区](http://www.ituring.com.cn/book/1874)为我们加油(推荐、收藏)! 12 | -------------------------------------------------------------------------------- /src/app/_shared/api/books/ng-book2/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/books/ng-book2/cover.png -------------------------------------------------------------------------------- /src/app/_shared/api/columns/_images/snowwolf.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/columns/_images/snowwolf.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/columns/_images/trotyl.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/columns/_images/trotyl.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/columns/index.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {Observable} from 'rxjs/Observable'; 3 | import {Column} from '../../models/column'; 4 | 5 | const items: Column[] = [ 6 | { 7 | id: '雪狼湖', 8 | name: '雪狼湖', 9 | bio: '感受一位十八年技术老兵的热忱', 10 | description: '茶前漫坐,听雪狼谈古论今,分析技术表里,享受不一样的思维盛宴', 11 | authors: ['雪狼'], 12 | tags: ['从前', '现在', '将来', '奇闻', '轶事', '放松', '烧脑'], 13 | avatar: require('./_images/snowwolf.jpg') 14 | }, 15 | { 16 | id: 'trotyl', 17 | name: `Trotyl's Workspace`, 18 | bio: '', 19 | description: '', 20 | authors: ['trotyl'], 21 | tags: [''], 22 | avatar: require('./_images/trotyl.jpg') 23 | } 24 | ]; 25 | 26 | @Injectable() 27 | export class ColumnApi { 28 | query(params = {}): Observable { 29 | return Observable.from(items); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/app/_shared/api/index.ts: -------------------------------------------------------------------------------- 1 | import {ThreadApi} from './threads/index'; 2 | import {ArticleApi} from './articles/index'; 3 | import {AuthorApi} from './authors/index'; 4 | import {BookApi} from './books/index'; 5 | import {ColumnApi} from './columns/index'; 6 | import {NewsApi} from './news/index'; 7 | import {PartnerApi} from './partners/index'; 8 | import {ResourceApi} from './resources/index'; 9 | import {ShowcaseApi} from './showcases/index'; 10 | export * from './articles'; 11 | export * from './authors'; 12 | export * from './books'; 13 | export * from './columns'; 14 | export * from './news'; 15 | export * from './partners'; 16 | export * from './resources'; 17 | export * from './showcases'; 18 | export * from './threads'; 19 | 20 | export const SHARED_APIS = [ArticleApi, AuthorApi, BookApi, ColumnApi, NewsApi, PartnerApi, ResourceApi, ShowcaseApi, ThreadApi]; 21 | -------------------------------------------------------------------------------- /src/app/_shared/api/news/10.Angular 2 Final即将到来/_index.md: -------------------------------------------------------------------------------- 1 | # Angular 2 Final即将到来 2 | 3 | ## 好消息! 4 | 5 | 为期两年半的长跑终于要结束了! 6 | 7 | Angular官方库的Milestone中已经没有了新的RC计划,目前剩下的三个是Angular 2 Final、2.0.1、2.1.0这几个。截止今日,Angular 2 Final里程碑中的问题已经解决了62%。以近期的速度估算,Angular 2应该有机会在九月底发布正式版。 8 | 9 | 在这两年半的历史中,Angular 2经历了56个alpha、18个beta和8个rc,共有324位来自Google和开源社区的贡献者提交了5500多个commit(笔者提交过两个PR)。 10 | 11 | ## 我们能做什么? 12 | 13 | 除了等待,我们还能做很多。 14 | 15 | 迄今为止,Angular开发组已经解决掉了issue有5800多个,还剩下1100多个尚解决的issue。除了被列入Milestone的之外,这些尚未解决的issue通常优先级都比较低。 16 | 17 | 我们能为此做什么呢? 18 | 19 | 首先,我们可以帮助官方开发组验证各个issue。剩下的这些issue是长久积累而来的,其中的一些已经在其它提交中被解决掉了,但官方开发组仍然需要花费人力去逐个验证它们。我们可以去帮助开发组验证它们是否仍然存在,如果不存在了,开发组就不需要再花精力去处理它们。 20 | 21 | 其次,对于一些能够重现的bug,我们可以帮助开发组定位它们,这有一定难度,不过对于锻炼自己的Angular水平很有帮助。 22 | 23 | 最后,如果你定位了它们,也可以尝试自己去解决,并且提交一个Pull Request。如果你的Pull Request被接受了,那么你将被列入Contributor名单中,这是一种荣誉。 24 | 25 | 除此之外,如果你的英语比较好,还可以帮助官方检查API文档。在漫长的开发过程中,某些API的文档可能没有同步更新。当你在开发中发现某些API的文档与行为不符时,请修改它们。 26 | 27 | ## 人人都能做的事! 28 | 29 | 当然,难度最低的方式是深入理解并宣传Angular,这既是对自己的提升,也是对社区的贡献! 30 | 31 | 心动不如行动! 32 | -------------------------------------------------------------------------------- /src/app/_shared/api/news/10.Angular 2 Final即将到来/final.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/app/_shared/api/news/20.Angular 2正式发布/homepage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/news/20.Angular 2正式发布/homepage.png -------------------------------------------------------------------------------- /src/app/_shared/api/news/index.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {Observable} from 'rxjs/Observable'; 3 | import {Article} from '../../models/article'; 4 | 5 | const items: Article[] = [ 6 | { 7 | id: 'Angular 2 Final即将到来!', 8 | image: require('./10.Angular 2 Final即将到来/final.svg'), 9 | title: 'Angular 2 Final即将到来!!', 10 | summary: 'Angular 2 Final即将到来,敬请期待', 11 | content: require('./10.Angular 2 Final即将到来/_index.md'), 12 | authors: ['雪狼'], 13 | }, 14 | { 15 | id: 'Angular 2正式发布', 16 | image: require('../../_images/angular.svg'), 17 | title: 'Angular 2正式发布', 18 | summary: '2016年中秋节,经过两年半的长跑,Angular 2终于正式发布了!', 19 | content: require('./20.Angular 2正式发布/_index.md'), 20 | authors: ['Jules Kremer'], 21 | translators: ['雪狼'], 22 | } 23 | ]; 24 | 25 | @Injectable() 26 | export class NewsApi { 27 | query(params = {}): Observable
{ 28 | return Observable.from(items); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/app/_shared/api/partners/_images/angular.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/app/_shared/api/partners/_images/tw-insights.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/partners/_images/tw-insights.jpg -------------------------------------------------------------------------------- /src/app/_shared/api/partners/index.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {Observable} from 'rxjs/Observable'; 3 | import {Partner} from '../../models/partner'; 4 | 5 | const items: Partner[] = [ 6 | { 7 | id: 'angular-io', 8 | avatar: require('./_images/angular.svg'), 9 | name: 'Angular官网(英文)', 10 | description: 'Angular 2官方网站,最新、最权威的技术资料', 11 | homepage: 'https://angular.io' 12 | }, 13 | { 14 | id: 'insignts', 15 | avatar: require('./_images/tw-insights.jpg'), 16 | name: 'ThoughtWorks洞见', 17 | description: 'ThoughtWorks中国区的精品文章汇总', 18 | homepage: 'http://insights.thoughtworkers.org/' 19 | } 20 | ]; 21 | 22 | @Injectable() 23 | export class PartnerApi { 24 | query(params = {}): Observable { 25 | return Observable.from(items); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/app/_shared/api/resources/20.fuel-ui/_index.md: -------------------------------------------------------------------------------- 1 | # Fuel UI评测 2 | 3 | ## 简介 4 | 5 | Fuel UI是对Bootstrap 4的原生封装,这意味着它使用Bootstrap的css组件,但是用Angular 2的方式代替了其js部分。 6 | 7 | 官方网站在 8 | 9 | ## 优点 10 | 11 | 封装比较全面,接口设计上比较友好。 12 | 13 | ## 缺点 14 | 15 | 缺少一些重要的交互功能,如Popover、Tooltip等 -------------------------------------------------------------------------------- /src/app/_shared/api/resources/20.fuel-ui/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/resources/20.fuel-ui/logo.png -------------------------------------------------------------------------------- /src/app/_shared/api/resources/30.awesome/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/_shared/api/resources/30.awesome/logo.png -------------------------------------------------------------------------------- /src/app/_shared/api/resources/index.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {Observable} from 'rxjs/Observable'; 3 | import {Article} from '../../models/article'; 4 | 5 | const items: Article[] = [ 6 | { 7 | id: 'Angular资源大全', 8 | image: require('../../_images/angular.svg'), 9 | title: 'Angular资源大全', 10 | summary: 'AngularClass收集的精品资源大全', 11 | content: require('./30.awesome/_index.md'), 12 | authors: ['AngularClass'], 13 | translators: ['雪狼'], 14 | originalUrl: 'https://github.com/AngularClass/awesome-angular2', 15 | }, 16 | { 17 | id: 'PrimeNg', 18 | image: require('./10.prime-ng/logo.svg'), 19 | title: 'PrimeNg简介', 20 | summary: '一套优秀的企业级Angular组件库', 21 | content: require('./10.prime-ng/_index.md'), 22 | authors: ['雪狼'], 23 | }, 24 | { 25 | id: 'Fuel UI', 26 | image: require('./20.fuel-ui/logo.png'), 27 | title: 'Fuel UI简介', 28 | summary: 'Angular 2原生Bootstrap组件', 29 | content: require('./20.fuel-ui/_index.md'), 30 | authors: ['雪狼'], 31 | } 32 | ]; 33 | 34 | @Injectable() 35 | export class ResourceApi { 36 | query(params = {}): Observable
{ 37 | return Observable.from(items); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/app/_shared/api/showcases/10.ifish简介/_index.md: -------------------------------------------------------------------------------- 1 | ## 项目背景 2 | 3 | 从水产品食物需求来说,FAO预测直至2030年,当中国人口总量达到峰值时,比现在增加近1.6亿,若按现在人均占有量41公斤计,中国水产品的需求量需要增加约1000万吨。另外,随着社会经济发展,生活水平提高,人均需求量也会增加,若按人均占有量50公斤计,还需要再增加近1000万吨。不同于发达国家以水产品的深海捕捞为主,中国的水产养殖占总水产品总量的75%以上,捕捞仅仅占1/4. ThoughtWorks在海洋和渔业方面的第一个项目经验可以追溯到4年前, 由武汉团队完成的SFP 的 离岸交付项目;第二个项目也就是今天上线的iFISH项目,即P3在本土与智渔 刚刚结束的合作项目。虽然后者是成立仅仅一年的致力于中国本土渔业的组织,前者是成立了10年关注海外渔业捕捞的NGO,但是两者的使命却保持一致,即通过调动和催化渔业供应链的健康发展来减少捕捞/养殖对环境的影响。 4 | 5 | ## 项目目标 6 | 7 | - 开发适用于中国水产品(包括养殖和捕捞,淡水和海水)之生产、加工、流通、消费场景下对其环境、社会、经济可持续性开展综合评价的方法学 (原理) 8 | - 建立一套直观、准确地反映中国水产品发展可持续性的评价指标和相匹配的数据库(工具) 9 | - 为水产供应链各利益相关方(包括消费者、零售商、采购商、生产商以及政府管理部门等)提供便捷、易用、科学的可持续发展决策依据(产品) 10 | 11 | ## 运营方简介 - 智渔科技 12 | 13 | 智渔可持续科技发展中心(简称“智渔”,英文名China Blue Sustainability Institute, 简称“China Blue”)成立于2015年2月,是中国本土第一家专注渔业资源可持续利用、海洋及海岸带生态环境保护的非营利组织。 通过跨学科、多视角、贴近行业的综合研究与实践,从社会、经济、文化和技术多维度探寻人与海洋的和谐发展之道。 14 | 15 | ## 开发方简介 - ThoughtWorks 16 | 17 | 我们不仅仅是一家软件公司,同时也是一个社区:我们汇集满怀激情的软件精英,通过技术和客户共同应对最艰巨的挑战。同时我们寻求IT行业的革新,并致力于对社会产生积极的影响力。 18 | 19 | ## 合作过程 20 | 21 | 智渔与ThoughtWorks的接触从这家组织成立的第一天起就开始了,而ThoughtWorks的价值也不仅仅体现在这个交付项目。从智渔建立行业品牌初期、与迪斯尼的合作直到iFISH的上线,ThoughtWorks伴随智渔的成长经历了三次重要事件: 22 | - 组织预备期:对组织的发展目标和业务进行整体梳理,帮助智渔制定了组织起步和发展的优先级计划,使创始人对组织在不同阶段的计划有了清晰的思考。 23 | - 项目筹备期:与众多利益相关方(包括品牌方(迪斯尼)、鱼类供应商、IICD专家和上海海洋大学教授)协同进行MVP产品设计 24 | - iFISH一期交付:帮助海产品采购商们(迪斯尼等)提供了允许交易的海产品的详细信息,而其中的信息是包含了食品安全和海洋环境指标的详细信息。 25 | 26 | ## 开发过程 27 | 28 | 本次开发采用前后端分离方案,前端基于Angular 2.0 RC3~RC4和Bootstrap 4 alpha版,中间还进行了一次路由库升级。前端部分由[雪狼](/library/author/雪狼)带领一位一年工作经验的新前端开发完成。 29 | 30 | ## 经验分享 31 | 32 | 本项目基于[社区的一个starter项目](https://github.com/AngularClass/angular2-webpack-starter),并进行了[适当改造](https://github.com/asnowwolf/angular2-webpack-starter)。这是一个相当完善的种子工程,不过仍然显得比较复杂,建议初学者不必深入了解细节。 33 | 34 | 在开发中,我们采用了以组件为中心的开发方式,形成了比较好的架构: 35 | 36 | - 初期,新手可以用copy/paste的方式进行开发,同时参照文档进行学习 37 | - 中期,新手就以这些经验为基础,逐步开始独立开发 38 | - 后期,新手可以独立开启一组相关的特性 39 | 40 | ## 心得 41 | 42 | 对于有新手参与的开发,架构的首要考虑就是营造安全区,这就意味着充分的代码隔离 —— 即使有烂代码,其影响范围也尽可能小。 43 | 44 | 在这个场景下,Angular 2中最有用的特性是“组件样式”隔离机制,写具有良好可维护性的CSS对于新手前端来说是个相当严峻的考验。而组件样式可以防止样式“溢出”组件范围,有效的减少了不必要的耦合。 45 | -------------------------------------------------------------------------------- /src/app/_shared/api/showcases/20.Angular BBS简介/_index.md: -------------------------------------------------------------------------------- 1 | # Angular BBS简介 2 | 3 | ## 这是什么? 4 | 5 | Angular BBS,也就是“Angular中文社区”公众号的后台支持程序,当你从微信公众号中点击“阅读原文”时,就会进入Angular BBS的“资料中心”页面。 6 | 7 | 这是一个用Angular 2写的开源BBS,特别针对移动端的体验进行优化。 8 | 9 | 它的主要设计目标是为“Angular中文社区”公众号提供支持,比如: 10 | 11 | - 让公众号图文消息的排版更灵活。 12 | - 弥补公众号图文消息一旦发出就无法修改的问题。 13 | - 弥补公众号图文消息中不能嵌入链接的问题。 14 | - 提供更强大的问答功能,能够让提问者很方便的使用Markdown描述问题,并提交代码。 15 | - 为程序员提供一个可以在上下班路上看的Angular 2文档库 - 只要你在Wifi环境下访问它,那么在路上时就不会消耗流量。 16 | 17 | 本论坛仍在开发中,目前是一个基于Angular 2的纯前端实现,并且做了一个后端API的原型。稍后我们会开始把前后端对接起来。 18 | 19 | ## 技术架构 20 | 21 | Angular BBS的全部源码(含文章)存放在Github上的[angular-bbs](https://github.com/angular-bbs)组下。 22 | 23 | 前端使用的是Angular 2的RC5版本,稍后会升级到Final。后端使用的是.NET Core,不过它目前的规划中不打算自带数据库,而是使用Github通行证登录,并通过Github的Issues API来把它提交到[q-and-a](https://github.com/angular-bbs/q-and-a)项目中。 24 | 25 | ## 我们需要你! 26 | 27 | Angular BBS是完全开源的项目,并且正在召集参与者,欢迎各位一同参与。你可以通过提Issue来告诉我们你的需求和使用场景;可以通过Pull Request来为我们贡献代码或稿件;如果你能够承诺投入很多时间和精力,还可以成为核心贡献者,请给我留言加入核心组。 28 | -------------------------------------------------------------------------------- /src/app/_shared/api/showcases/index.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {Showcase} from '../../models/showcase'; 3 | import {Observable} from 'rxjs/Observable'; 4 | const items: Showcase[] = [ 5 | { 6 | id: 'iFish', 7 | title: 'iFISH', 8 | url: 'http://www.ifishonline.org/', 9 | author: 'ThoughtWorks', 10 | customer: '智渔科技', 11 | description: require('./10.ifish简介/_index.md'), 12 | picture: require('./10.ifish简介/_images/ifish.svg'), 13 | }, 14 | { 15 | id: 'Angular BBS简介', 16 | title: 'Angular BBS简介', 17 | url: 'https://wx.angular.cn', 18 | author: '雪狼', 19 | customer: '开源项目', 20 | description: require('./20.Angular BBS简介/_index.md'), 21 | picture: require('./20.Angular BBS简介/logo.svg'), 22 | }, 23 | ]; 24 | @Injectable() 25 | export class ShowcaseApi { 26 | query(params = {}): Observable { 27 | return Observable.from(items); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/app/_shared/api/threads/10.欢迎您!陌生的旅者.md: -------------------------------------------------------------------------------- 1 | # 欢迎您!陌生的旅者! 2 | 3 | 能迎来您这样一位勇士是本社区的荣幸! 4 | 5 | ---- 6 | 7 | **NPC模式结束** 8 | 9 | -------------------------------------------------------------------------------- /src/app/_shared/api/threads/20.悬赏!哥德巴赫猜想.md: -------------------------------------------------------------------------------- 1 | 悬赏征求哥德巴赫猜想的证明! -------------------------------------------------------------------------------- /src/app/_shared/api/threads/30.Angular 2路由问题.md: -------------------------------------------------------------------------------- 1 | 我在把Angular 2的路由从RC.1升级到RC.4时遇到了如下问题,请高手帮忙解决: 2 | 3 | 现象如下: 4 | 5 | > 无法跳转 6 | 7 | 代码如下: 8 | ```typescript 9 | 10 | const a = 1; 11 | 12 | ``` -------------------------------------------------------------------------------- /src/app/_shared/api/threads/index.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {Thread} from '../../models/thread'; 3 | import {Observable} from 'rxjs/Observable'; 4 | const items: Thread[] = [ 5 | { 6 | id: '1', 7 | title: '欢迎您!陌生的旅者', 8 | picture: require('./_images/wizard.svg'), 9 | content: require('./10.欢迎您!陌生的旅者.md'), 10 | authors: ['雪狼', '叶志敏'], 11 | labels: ['hot', 'latest'], 12 | }, 13 | { 14 | id: '2', 15 | title: '悬赏!哥德巴赫猜想', 16 | content: require('./20.悬赏!哥德巴赫猜想.md'), 17 | authors: ['雪狼'], 18 | labels: ['latest', 'reward'], 19 | }, 20 | { 21 | id: '3', 22 | title: 'Angular 2路由问题', 23 | content: require('./30.Angular 2路由问题.md'), 24 | authors: ['雪狼'], 25 | labels: [], 26 | }, 27 | ]; 28 | @Injectable() 29 | export class ThreadApi { 30 | query(filter: string = 'all'): Observable { 31 | return Observable.from(items) 32 | .filter((item: Thread)=> { 33 | switch (filter) { 34 | case 'mine': 35 | return item.authors.indexOf('雪狼') !== -1; 36 | case 'hot': 37 | return item.labels.indexOf('hot') !== -1; 38 | case 'latest': 39 | return item.labels.indexOf('latest') !== -1; 40 | case 'reward': 41 | return item.labels.indexOf('reward') !== -1; 42 | default: 43 | return true; 44 | } 45 | }) 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /src/app/_shared/components/base/page.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, OnDestroy } from '@angular/core'; 2 | import { ActivatedRoute } from '@angular/router'; 3 | import { Subscription } from 'rxjs/Subscription'; 4 | import { StringMap } from '../../utils/index'; 5 | 6 | @Component({ template: '' }) 7 | export abstract class BasePageComponent implements OnInit, OnDestroy { 8 | constructor(protected activatedRoute: ActivatedRoute) { 9 | } 10 | 11 | activatedRouteSubscription: Subscription; 12 | 13 | ngOnInit() { 14 | this.activatedRouteSubscription = this.activatedRoute.params.subscribe((params) => { 15 | this.reload(params); 16 | }); 17 | } 18 | 19 | ngOnDestroy() { 20 | this.activatedRouteSubscription.unsubscribe(); 21 | } 22 | 23 | abstract reload(params: StringMap): void; 24 | } 25 | -------------------------------------------------------------------------------- /src/app/_shared/components/html/viewer.component.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /src/app/_shared/components/html/viewer.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input, OnChanges, SimpleChange } from '@angular/core'; 2 | import { SafeHtml, DomSanitizer } from '@angular/platform-browser'; 3 | import { SimpleChanges } from '@angular/core'; 4 | 5 | @Component({ 6 | selector: 'html-viewer', 7 | templateUrl: './viewer.component.html', 8 | styleUrls: [ 9 | './viewer.component.scss' 10 | ], 11 | }) 12 | export class HtmlViewerComponent implements OnChanges { 13 | @Input() content: string; 14 | private html: SafeHtml; 15 | 16 | constructor(private sanitizer: DomSanitizer) { 17 | } 18 | 19 | ngOnChanges(changes: SimpleChanges): void { 20 | const change: SimpleChange = changes['content']; 21 | if (change.currentValue) { 22 | this.html = this.sanitizer.bypassSecurityTrustHtml(change.currentValue); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/app/_shared/components/index.ts: -------------------------------------------------------------------------------- 1 | import { BasePageComponent } from './base/page.component'; 2 | import { HtmlViewerComponent } from './html/viewer.component'; 3 | import { LayoutNavComponent } from './layout/nav.component'; 4 | import { MenuListComponent } from './menu/list.component'; 5 | export * from './base/page.component'; 6 | export * from './html/viewer.component'; 7 | export * from './layout/nav.component'; 8 | export * from './menu/list.component'; 9 | 10 | export const SHARED_COMPONENTS = [ 11 | // BasePageComponent, 12 | HtmlViewerComponent, 13 | LayoutNavComponent, 14 | MenuListComponent 15 | ]; 16 | -------------------------------------------------------------------------------- /src/app/_shared/components/layout/nav.component.html: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /src/app/_shared/components/layout/nav.component.scss: -------------------------------------------------------------------------------- 1 | @import '../../styles/common'; 2 | 3 | :host { 4 | display: block; 5 | } 6 | 7 | .nav { 8 | .nav-item { 9 | width: 33.3333%; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/app/_shared/components/layout/nav.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'layout-nav', 5 | templateUrl: './nav.component.html', 6 | styleUrls: [ 7 | './nav.component.scss' 8 | ], 9 | 10 | }) 11 | export class LayoutNavComponent implements OnInit { 12 | constructor() { 13 | } 14 | 15 | ngOnInit() { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/app/_shared/components/menu/list.component.html: -------------------------------------------------------------------------------- 1 | 21 | -------------------------------------------------------------------------------- /src/app/_shared/components/menu/list.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../styles/common"; 2 | 3 | :host { 4 | display: block; 5 | margin: 0 -1rem; 6 | } 7 | 8 | .list-group-item { 9 | padding: 0.5rem 0.75rem; 10 | border-left: none; 11 | border-right: none; 12 | } 13 | 14 | .media-right { 15 | vertical-align: middle; 16 | color: $text-muted; 17 | } 18 | 19 | .media-heading { 20 | margin-bottom: 1rem; 21 | } 22 | 23 | .media-body { 24 | p { 25 | font-size: 0.9rem; 26 | color: $text-muted; 27 | &:last-child { 28 | margin-bottom: 0; 29 | } 30 | } 31 | } 32 | 33 | .media-left { 34 | min-width: 80px; 35 | .media-object { 36 | margin: auto; 37 | } 38 | } 39 | .icon { 40 | font-size: 1.5rem; 41 | } 42 | -------------------------------------------------------------------------------- /src/app/_shared/components/menu/list.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, Input} from '@angular/core'; 2 | import {MenuItem} from '../../models/menu-item'; 3 | 4 | @Component({ 5 | selector: 'menu-list', 6 | templateUrl: './list.component.html', 7 | styleUrls: [ 8 | './list.component.scss' 9 | ], 10 | 11 | }) 12 | export class MenuListComponent implements OnInit { 13 | constructor() { 14 | } 15 | 16 | @Input() items: MenuItem[]; 17 | 18 | ngOnInit() { 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/app/_shared/index.ts: -------------------------------------------------------------------------------- 1 | export * from './api'; 2 | export * from './components'; 3 | export * from './models'; 4 | export * from './operators'; 5 | export * from './pipes'; 6 | export * from './services'; 7 | export * from './utils'; 8 | -------------------------------------------------------------------------------- /src/app/_shared/models/article.ts: -------------------------------------------------------------------------------- 1 | export interface Article { 2 | id: string; 3 | /** 标题 */ 4 | title: string; 5 | /** 题图 */ 6 | image?: string; 7 | /** 简介 */ 8 | summary?: string; 9 | /** 内容 */ 10 | content: string; 11 | /** 作者id */ 12 | authors: string[]; 13 | /** 译者id */ 14 | translators?: string[]; 15 | /** 是否转载 */ 16 | forward?: boolean; 17 | /** 是否翻译 */ 18 | translation?: boolean; 19 | /** 是否首发 */ 20 | first?: boolean; 21 | /** 是否独家 */ 22 | exclusive?: boolean; 23 | /** 所属专栏id */ 24 | column?: string; 25 | /** 标签 */ 26 | tags?: string[]; 27 | /** 原地址 */ 28 | originalUrl?: string; 29 | /** 是否隐藏 */ 30 | hidden?: boolean; 31 | } 32 | -------------------------------------------------------------------------------- /src/app/_shared/models/author.ts: -------------------------------------------------------------------------------- 1 | export interface Author { 2 | id: string; 3 | /** 姓名 */ 4 | name: string; 5 | /** 头像 */ 6 | avatar: string; 7 | /** 一句话简介 */ 8 | bio: string; 9 | /** 详细描述 */ 10 | description: string; 11 | /** 是否专栏作家 */ 12 | columnist?: boolean; 13 | homepage?: string; 14 | } 15 | -------------------------------------------------------------------------------- /src/app/_shared/models/book.ts: -------------------------------------------------------------------------------- 1 | import {Link} from './link'; 2 | export interface Book { 3 | id: string; 4 | picture: string; 5 | title: string; 6 | description: string; 7 | storeUrls: Link[]; 8 | authors: string[]; 9 | translators?: string[]; 10 | isbn?: string; 11 | } 12 | -------------------------------------------------------------------------------- /src/app/_shared/models/column.ts: -------------------------------------------------------------------------------- 1 | export interface Column { 2 | id: string; 3 | name: string; 4 | avatar: string; 5 | bio: string; 6 | description: string; 7 | tags: string[]; 8 | authors: string[]; 9 | } 10 | -------------------------------------------------------------------------------- /src/app/_shared/models/index.ts: -------------------------------------------------------------------------------- 1 | export * from './article'; 2 | export * from './author'; 3 | export * from './book'; 4 | export * from './column'; 5 | export * from './link'; 6 | export * from './menu-item'; 7 | export * from './partner'; 8 | export * from './showcase'; 9 | export * from './thread'; 10 | -------------------------------------------------------------------------------- /src/app/_shared/models/link.ts: -------------------------------------------------------------------------------- 1 | export class Link { 2 | constructor(private url: string, private title?: string) { 3 | } 4 | } 5 | -------------------------------------------------------------------------------- /src/app/_shared/models/menu-item.ts: -------------------------------------------------------------------------------- 1 | export interface MenuItem { 2 | title: string; 3 | icon?: string; 4 | description: string; 5 | url: string; 6 | } 7 | -------------------------------------------------------------------------------- /src/app/_shared/models/partner.ts: -------------------------------------------------------------------------------- 1 | export interface Partner { 2 | id: string; 3 | name: string; 4 | avatar: string; 5 | description: string; 6 | homepage: string; 7 | } 8 | -------------------------------------------------------------------------------- /src/app/_shared/models/showcase.ts: -------------------------------------------------------------------------------- 1 | export interface Showcase { 2 | id: string; 3 | picture: string; 4 | title: string; 5 | description: string; 6 | author: string; 7 | customer: string; 8 | url?: string; 9 | } 10 | -------------------------------------------------------------------------------- /src/app/_shared/models/thread.ts: -------------------------------------------------------------------------------- 1 | import {Article} from './article'; 2 | export interface Thread { 3 | id: string; 4 | /** 题图 */ 5 | picture?: string; 6 | /** 标题 */ 7 | title: string; 8 | /** 内容 */ 9 | content: string; 10 | /** 作者id */ 11 | authors: string[]; 12 | /** 内容标签,tag */ 13 | tags?: string[]; 14 | /** 分类标签,类似于Github的分类 */ 15 | labels?: string[]; 16 | /** 帖子的回复 */ 17 | comments?: Article[]; 18 | } 19 | -------------------------------------------------------------------------------- /src/app/_shared/operators/index.ts: -------------------------------------------------------------------------------- 1 | export * from './match-by-id'; 2 | -------------------------------------------------------------------------------- /src/app/_shared/operators/match-by-id.ts: -------------------------------------------------------------------------------- 1 | export function matchById(id: string) { 2 | return function match(item: Object) { 3 | return !id || item && item['id'] === id; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/app/_shared/pipes/index.ts: -------------------------------------------------------------------------------- 1 | import { TrustAsImgUrlPipe } from './trust-as-img-url'; 2 | export * from './trust-as-img-url'; 3 | 4 | export const SHARED_PIPES = [TrustAsImgUrlPipe]; 5 | -------------------------------------------------------------------------------- /src/app/_shared/pipes/trust-as-img-url.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from '@angular/core'; 2 | import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; 3 | @Pipe({ 4 | name: 'trustAsImgUrl' 5 | }) 6 | export class TrustAsImgUrlPipe implements PipeTransform { 7 | constructor(private sanitizer: DomSanitizer) { 8 | } 9 | 10 | transform(url: string): SafeResourceUrl { 11 | return this.sanitizer.bypassSecurityTrustUrl(url); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/app/_shared/services/auth.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import * as uuid from 'uuid'; 3 | 4 | @Injectable() 5 | export class Auth { 6 | constructor() { 7 | if (!this.csrfToken) { 8 | this.nextCsrfToken(); 9 | } 10 | } 11 | 12 | get csrfToken(): string { 13 | return sessionStorage.getItem('csrfToken'); 14 | } 15 | 16 | set csrfToken(value: string) { 17 | sessionStorage.setItem('csrfToken', value); 18 | } 19 | 20 | code: string; 21 | 22 | nextCsrfToken(): void { 23 | this.csrfToken = uuid.v4(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/app/_shared/services/change-title.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {CanActivateChild, ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router'; 3 | import {Title} from '@angular/platform-browser'; 4 | 5 | @Injectable() 6 | export class ChangeTitle implements CanActivateChild { 7 | constructor(private title: Title) { 8 | } 9 | 10 | canActivateChild(childRoute: ActivatedRouteSnapshot, 11 | state: RouterStateSnapshot) { 12 | let route: ActivatedRouteSnapshot = childRoute; 13 | let routes: ActivatedRouteSnapshot[] = []; 14 | while (route) { 15 | routes.push(route); 16 | route = route.parent; 17 | } 18 | const title = routes 19 | .filter(route => route.data && (route.data).title) 20 | .map(route => (route.data).title) 21 | .join(' / '); 22 | this.title.setTitle(title); 23 | 24 | return true; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/app/_shared/services/index.ts: -------------------------------------------------------------------------------- 1 | import {Auth} from "./auth"; 2 | import {ChangeTitle} from "./change-title"; 3 | export * from './auth'; 4 | export * from './change-title'; 5 | 6 | export const SHARED_SERVICES = [Auth, ChangeTitle]; 7 | -------------------------------------------------------------------------------- /src/app/_shared/styles/_app.scss: -------------------------------------------------------------------------------- 1 | @import "variables"; 2 | 3 | svg.icon { 4 | height: 1em; 5 | width: 1em; 6 | position: relative; 7 | bottom: -0.1em; 8 | * { 9 | fill: currentcolor; 10 | } 11 | } 12 | 13 | @import "~highlight.js/styles/github.css"; 14 | 15 | h2 { 16 | font-size: 20px; 17 | color: $brand-secondary; 18 | margin-bottom: 20px; 19 | } 20 | -------------------------------------------------------------------------------- /src/app/_shared/styles/_bootstrap-extends.scss: -------------------------------------------------------------------------------- 1 | @import "common"; 2 | 3 | .media { 4 | .media-object { 5 | height: 64px; 6 | max-width: 64px; 7 | } 8 | } 9 | 10 | .padding-h-neg { 11 | margin-left: -1rem; 12 | margin-right: -1rem; 13 | &.list-group { 14 | > .list-group-item { 15 | border-left: none; 16 | border-right: none; 17 | } 18 | } 19 | } 20 | 21 | .breadcrumb { 22 | margin-bottom: 0; 23 | } 24 | 25 | ol { 26 | padding-left: 1rem; 27 | } 28 | 29 | ul { 30 | padding-left: 1rem; 31 | } 32 | 33 | .nav.nav-simple { 34 | @include clearfix(); 35 | .nav-link { 36 | display: block; 37 | padding: .5em 1em; 38 | border-radius: 0; 39 | } 40 | .nav-item { 41 | float: left; 42 | & + .nav-item { 43 | margin-left: 0; 44 | } 45 | .nav-link { 46 | text-align: center; 47 | cursor: default; 48 | &.active { 49 | color: $brand-secondary; 50 | background: none; 51 | border-bottom: 2px solid $brand-secondary; 52 | border-radius: 0; 53 | } 54 | } 55 | } 56 | } 57 | 58 | .sticky { 59 | position: fixed !important; 60 | &.sticky-bottom-right { 61 | bottom: 1em; 62 | right: 1em; 63 | } 64 | } 65 | 66 | .btn { 67 | &.btn-secondary { 68 | background: $brand-secondary; 69 | color: $gray-lightest; 70 | } 71 | } 72 | 73 | blockquote { 74 | padding-left: 1rem; 75 | border-left: 2px solid $brand-secondary; 76 | } 77 | -------------------------------------------------------------------------------- /src/app/_shared/styles/_bootstrap.scss: -------------------------------------------------------------------------------- 1 | @import "common"; 2 | /*! 3 | * Bootstrap v4.0.0-alpha.3 (http://getbootstrap.com) 4 | * Copyright 2011-2016 The Bootstrap Authors 5 | * Copyright 2011-2016 Twitter, Inc. 6 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 7 | */ 8 | // Core variables and mixins 9 | @import "~bootstrap/scss/custom"; 10 | @import "~bootstrap/scss/variables"; 11 | @import "~bootstrap/scss/mixins"; 12 | // Reset and dependencies 13 | @import "~bootstrap/scss/normalize"; 14 | @import "~bootstrap/scss/print"; 15 | // Core CSS 16 | @import "~bootstrap/scss/reboot"; 17 | @import "~bootstrap/scss/type"; 18 | @import "~bootstrap/scss/images"; 19 | @import "~bootstrap/scss/code"; 20 | @import "~bootstrap/scss/grid"; 21 | @import "~bootstrap/scss/tables"; 22 | @import "~bootstrap/scss/forms"; 23 | @import "~bootstrap/scss/buttons"; 24 | // Components 25 | @import "~bootstrap/scss/animation"; 26 | @import "~bootstrap/scss/dropdown"; 27 | @import "~bootstrap/scss/button-group"; 28 | @import "~bootstrap/scss/input-group"; 29 | @import "~bootstrap/scss/custom-forms"; 30 | @import "~bootstrap/scss/nav"; 31 | @import "~bootstrap/scss/navbar"; 32 | @import "~bootstrap/scss/card"; 33 | @import "~bootstrap/scss/breadcrumb"; 34 | @import "~bootstrap/scss/pagination"; 35 | @import "~bootstrap/scss/tags"; 36 | @import "~bootstrap/scss/jumbotron"; 37 | @import "~bootstrap/scss/alert"; 38 | @import "~bootstrap/scss/progress"; 39 | @import "~bootstrap/scss/media"; 40 | @import "~bootstrap/scss/list-group"; 41 | @import "~bootstrap/scss/responsive-embed"; 42 | @import "~bootstrap/scss/close"; 43 | // Components w/ JavaScript 44 | @import "~bootstrap/scss/modal"; 45 | @import "~bootstrap/scss/tooltip"; 46 | @import "~bootstrap/scss/popover"; 47 | @import "~bootstrap/scss/carousel"; 48 | // Utility classes 49 | @import "~bootstrap/scss/utilities"; 50 | -------------------------------------------------------------------------------- /src/app/_shared/styles/_common.scss: -------------------------------------------------------------------------------- 1 | @import "variables"; 2 | @import "mixins"; 3 | -------------------------------------------------------------------------------- /src/app/_shared/styles/_material.scss: -------------------------------------------------------------------------------- 1 | @import './common'; 2 | 3 | .btn { 4 | @include raised(); 5 | &.btn-fab { 6 | border-radius: 50%; 7 | font-size: 24px; 8 | width: 2em; 9 | height: 2em; 10 | padding: 0; 11 | line-height: 2em; 12 | vertical-align: middle; 13 | text-align: center; 14 | overflow: hidden; 15 | box-shadow: 0 1px 1.5px 0 rgba(0, 0, 0, .12), 0 1px 1px 0 rgba(0, 0, 0, .24); 16 | position: relative; 17 | } 18 | } 19 | 20 | .nav { 21 | &.nav-tabs { 22 | border-bottom: none; 23 | background: $brand-primary; 24 | > .nav-item { 25 | margin-bottom: 0; 26 | + .nav-item { 27 | margin-left: 0; 28 | } 29 | .nav-link { 30 | text-align: center; 31 | border: none; 32 | background: $brand-primary; 33 | color: $gray-lightest; 34 | border-radius: 0; 35 | border-bottom: 2px solid transparent; 36 | &.active { 37 | color: $gray-lightest; 38 | border: none; 39 | border-bottom: 2px solid $brand-secondary; 40 | } 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/app/_shared/styles/_mixins.scss: -------------------------------------------------------------------------------- 1 | @import "variables"; 2 | @import "~bootstrap/scss/mixins"; 3 | 4 | @mixin raised() { 5 | box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12); 6 | } 7 | 8 | @mixin z-depth-0() { 9 | box-shadow: none; 10 | } 11 | 12 | @mixin z-depth-1() { 13 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); 14 | } 15 | 16 | @mixin z-depth-2() { 17 | box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); 18 | } 19 | 20 | @mixin z-depth-3() { 21 | box-shadow: 0 12px 15px 0 rgba(0, 0, 0, 0.24), 0 17px 50px 0 rgba(0, 0, 0, 0.19); 22 | } 23 | 24 | @mixin z-depth-4() { 25 | box-shadow: 0 16px 28px 0 rgba(0, 0, 0, 0.22), 0 25px 55px 0 rgba(0, 0, 0, 0.21); 26 | } 27 | 28 | @mixin z-depth-5() { 29 | box-shadow: 0 27px 24px 0 rgba(0, 0, 0, 0.2), 0 40px 77px 0 rgba(0, 0, 0, 0.22); 30 | } 31 | 32 | @mixin block-quote() { 33 | border-left: 2px solid $brand-primary; 34 | color: $gray-light; 35 | padding-left: 1rem; 36 | margin-bottom: 1rem; 37 | } 38 | -------------------------------------------------------------------------------- /src/app/_shared/styles/_variables.scss: -------------------------------------------------------------------------------- 1 | $border-radius: 0; 2 | 3 | $font-size-h1: 1.5rem; 4 | $font-size-h2: 1.2rem; 5 | $font-size-h3: 1rem; 6 | $font-size-h4: 1rem; 7 | $font-size-h5: 1rem; 8 | $font-size-h6: 1rem; 9 | 10 | $google-blue: #4885ed; 11 | $google-red: #DD0031; 12 | $google-yellow: #f4c20d; 13 | $google-green: #3cba54; 14 | 15 | $brand-primary: $google-blue; 16 | $link-color: $google-blue; 17 | $brand-secondary: $google-red; 18 | 19 | $brand-warning: $google-yellow; 20 | $brand-success: $google-green; 21 | 22 | $breadcrumb-bg: none; 23 | 24 | $breadcrumb-padding-x: 0; 25 | 26 | @import "~bootstrap/scss/variables"; 27 | -------------------------------------------------------------------------------- /src/app/_shared/utils/index.ts: -------------------------------------------------------------------------------- 1 | export interface StringMap { 2 | [s: string]: string; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/about/_README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/about/_README.md -------------------------------------------------------------------------------- /src/app/about/_about-routing.module.ts: -------------------------------------------------------------------------------- 1 | import {RouterModule, Routes} from '@angular/router'; 2 | import {AboutHomeComponent} from './home.component'; 3 | import {AboutJoinComponent} from './join.component'; 4 | import {AboutSiteComponent} from './site.component'; 5 | import {AboutUsComponent} from './us.component'; 6 | import {BookShowComponent} from './book/show.component'; 7 | import {BookHomeComponent} from './book/home.component'; 8 | import {ShowcaseShowComponent} from './showcase/show.component'; 9 | import {ShowcaseHomeComponent} from './showcase/home.component'; 10 | import {NgModule} from '@angular/core'; 11 | const routes: Routes = [ 12 | {path: '', pathMatch: 'full', data: {title: '首页'}, component: AboutHomeComponent}, 13 | {path: 'join', data: {title: '合作共赢'}, component: AboutJoinComponent}, 14 | {path: 'site', data: {title: '中文官网'}, component: AboutSiteComponent}, 15 | {path: 'us', data: {title: '中文社区'}, component: AboutUsComponent}, 16 | { 17 | path: 'book', 18 | data: {title: '图书推荐'}, 19 | children: [ 20 | {path: '', pathMatch: 'full', component: BookHomeComponent}, 21 | {path: ':id', component: BookShowComponent}, 22 | ], 23 | }, 24 | { 25 | path: 'showcase', 26 | data: {title: '成功案例'}, 27 | children: [ 28 | {path: '', pathMatch: 'full', component: ShowcaseHomeComponent}, 29 | {path: ':id', component: ShowcaseShowComponent}, 30 | ], 31 | }, 32 | ]; 33 | 34 | @NgModule({ 35 | imports: [RouterModule.forChild(routes)], 36 | exports: [RouterModule] 37 | }) 38 | 39 | export class AboutRoutingModule { 40 | } 41 | -------------------------------------------------------------------------------- /src/app/about/_about.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {CommonModule} from '@angular/common'; 3 | import {ABOUT_COMPONENTS} from './index'; 4 | import SharedModule from '../_shared/_shared.module'; 5 | import {AboutRoutingModule} from './_about-routing.module'; 6 | import {RouterModule} from '@angular/router'; 7 | import {BOOK_COMPONENTS} from './book/index'; 8 | import {SHOWCASE_COMPONENTS} from './showcase/index'; 9 | 10 | @NgModule({ 11 | imports: [ 12 | CommonModule, 13 | RouterModule, 14 | SharedModule, 15 | AboutRoutingModule, 16 | ], 17 | declarations: [...ABOUT_COMPONENTS, ...BOOK_COMPONENTS, ...SHOWCASE_COMPONENTS], 18 | }) 19 | export default class AboutModule { 20 | } 21 | -------------------------------------------------------------------------------- /src/app/about/_images/angular.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | angular 6 | Created with Sketch. 7 | 8 | 9 | 10 | 13 | 14 | 16 | 18 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/app/about/_images/books.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | books 6 | Created with Sketch. 7 | 8 | 9 | 10 | 13 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/app/about/_images/chevron-right.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /src/app/about/book/_README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/about/book/_README.md -------------------------------------------------------------------------------- /src/app/about/book/details.component.html: -------------------------------------------------------------------------------- 1 |
2 | 书籍封面 3 |
4 |

5 | {{item.title}} 6 |

7 | 8 |
9 |
10 | 作者: 11 | {{author}} 12 |
13 |
14 | 译者: 15 | {{translator}} 16 |
17 |
18 | 购买: 19 | {{store.title}} 20 |
21 |
22 |
23 | -------------------------------------------------------------------------------- /src/app/about/book/details.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../_shared/styles/common"; 2 | 3 | :host { 4 | display: block; 5 | } 6 | 7 | .card { 8 | border: none; 9 | } 10 | 11 | h2.card-title { 12 | text-align: center; 13 | color: $brand-inverse; 14 | } 15 | 16 | h3.card-title { 17 | text-align: center; 18 | color: $brand-primary; 19 | } 20 | 21 | .card-block { 22 | padding: 0; 23 | } 24 | 25 | .card-link { 26 | display: inline-block; 27 | padding: 0.5rem 0.5rem; 28 | & + .card-link { 29 | margin-left: 0; 30 | } 31 | } 32 | 33 | .card-img-top { 34 | display: block; 35 | max-width: 50%; 36 | margin: 0 auto 32px; 37 | } 38 | -------------------------------------------------------------------------------- /src/app/about/book/details.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, Input} from '@angular/core'; 2 | import {Book} from '../../_shared'; 3 | 4 | @Component({ 5 | selector: 'book-details', 6 | templateUrl: './details.component.html', 7 | styleUrls: [ 8 | './details.component.scss' 9 | ], 10 | }) 11 | export class BookDetailsComponent implements OnInit { 12 | 13 | @Input() item: Book; 14 | 15 | constructor() { 16 | } 17 | 18 | ngOnInit() { 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/app/about/book/home.component.html: -------------------------------------------------------------------------------- 1 |
2 | 5 |
6 | 7 | -------------------------------------------------------------------------------- /src/app/about/book/home.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/about/book/home.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {ActivatedRoute} from '@angular/router'; 3 | import {BookApi, BasePageComponent, Book, MenuItem} from '../../_shared'; 4 | import {Observable} from 'rxjs/Observable'; 5 | 6 | @Component({ 7 | selector: 'book-home', 8 | templateUrl: './home.component.html', 9 | styleUrls: [ 10 | './home.component.scss' 11 | ], 12 | 13 | }) 14 | export class BookHomeComponent extends BasePageComponent { 15 | constructor(activatedRoute: ActivatedRoute, private api: BookApi) { 16 | super(activatedRoute); 17 | } 18 | 19 | items: Observable; 20 | 21 | reload(params): void { 22 | this.items = this.api.query() 23 | .map(bookToMenuItem) 24 | .toArray(); 25 | } 26 | } 27 | 28 | function bookToMenuItem(book: Book): MenuItem { 29 | return { 30 | title: book.title, 31 | icon: book.picture, 32 | description: `作者:${book.authors.join(' ')}`, 33 | url: `/about/book/${book.id}` 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/app/about/book/index.ts: -------------------------------------------------------------------------------- 1 | import {BookDetailsComponent} from './details.component'; 2 | import {BookListComponent} from './list.component'; 3 | import {BookHomeComponent} from './home.component'; 4 | import {BookShowComponent} from './show.component'; 5 | export * from './details.component'; 6 | export * from './home.component'; 7 | export * from './list.component'; 8 | export * from './show.component'; 9 | 10 | export const BOOK_COMPONENTS = [BookDetailsComponent, BookListComponent, BookHomeComponent, BookShowComponent]; 11 | -------------------------------------------------------------------------------- /src/app/about/book/list.component.html: -------------------------------------------------------------------------------- 1 |
2 | 没有找到符合条件的图书 3 |
4 | 5 | -------------------------------------------------------------------------------- /src/app/about/book/list.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/about/book/list.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, Input} from '@angular/core'; 2 | import {MenuItem} from '../../_shared'; 3 | 4 | @Component({ 5 | selector: 'book-list', 6 | templateUrl: './list.component.html', 7 | styleUrls: [ 8 | './list.component.scss' 9 | ], 10 | 11 | }) 12 | export class BookListComponent implements OnInit { 13 | constructor() { 14 | } 15 | 16 | @Input() items: MenuItem[]; 17 | 18 | ngOnInit() { 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/app/about/book/show.component.html: -------------------------------------------------------------------------------- 1 |
2 | 8 |
9 | 10 | -------------------------------------------------------------------------------- /src/app/about/book/show.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/about/book/show.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {BasePageComponent, BookApi, Book, matchById} from '../../_shared'; 3 | import {ActivatedRoute} from '@angular/router'; 4 | import {Observable} from 'rxjs/Observable'; 5 | 6 | @Component({ 7 | selector: 'book-show', 8 | templateUrl: './show.component.html', 9 | styleUrls: [ 10 | './show.component.scss' 11 | ], 12 | 13 | }) 14 | export class BookShowComponent extends BasePageComponent { 15 | constructor(activatedRoute: ActivatedRoute, private api: BookApi) { 16 | super(activatedRoute); 17 | } 18 | 19 | item: Observable; 20 | 21 | reload(params: {id: string}): void { 22 | this.item = this.api.query() 23 | .find(matchById(params.id)) 24 | .do((item: Book)=> { 25 | document.title = `${item.title} - Angular中文社区`; 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/app/about/home.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/app/about/home.component.scss: -------------------------------------------------------------------------------- 1 | @import "../_shared/styles/common"; 2 | 3 | :host { 4 | display: block; 5 | padding-top: 1rem; 6 | } 7 | 8 | .collection { 9 | position: relative; 10 | .more-arrow { 11 | position: absolute; 12 | top: 0; 13 | right: 10px; 14 | height: 100%; 15 | width: 50px; 16 | path { 17 | fill: lighten($brand-primary, 10%); 18 | } 19 | } 20 | } 21 | 22 | h3 { 23 | margin-top: 1rem; 24 | } 25 | 26 | p { 27 | color: lighten($brand-primary, 5%); 28 | } 29 | -------------------------------------------------------------------------------- /src/app/about/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { MenuItem } from '../_shared'; 3 | import { Router } from '@angular/router'; 4 | 5 | @Component({ 6 | selector: 'about-home', 7 | templateUrl: './home.component.html', 8 | styleUrls: [ 9 | './home.component.scss' 10 | ], 11 | 12 | }) 13 | export class AboutHomeComponent implements OnInit { 14 | constructor(private router: Router) { 15 | } 16 | 17 | items: MenuItem[] = [ 18 | { 19 | title: '中文社区', 20 | description: '历史、现状、成员、活动', 21 | icon: require('./_images/about.svg'), 22 | url: './us' 23 | }, 24 | { 25 | title: '中文官网', 26 | description: '中文版的教程、指南等', 27 | icon: require('./_images/angular.svg'), 28 | url: './site' 29 | }, 30 | { 31 | title: '图书推荐', 32 | description: '中英文技术书籍推荐', 33 | icon: require('./_images/books.svg'), 34 | url: './book' 35 | }, 36 | { 37 | title: '成功案例', 38 | description: '国内外企业中的成功案例', 39 | icon: require('./_images/showcase.svg'), 40 | url: './showcase' 41 | }, 42 | { 43 | title: '合作共赢', 44 | description: '来!一起推动的繁荣', 45 | icon: require('./_images/handshake.svg'), 46 | url: './join' 47 | }, 48 | ]; 49 | 50 | ngOnInit() { 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/app/about/index.ts: -------------------------------------------------------------------------------- 1 | import {AboutHomeComponent} from './home.component'; 2 | import {AboutJoinComponent} from './join.component'; 3 | import {AboutSiteComponent} from './site.component'; 4 | import {AboutUsComponent} from './us.component'; 5 | 6 | export * from './home.component'; 7 | export * from './join.component'; 8 | export * from './site.component'; 9 | export * from './us.component'; 10 | export * from './book'; 11 | export * from './showcase'; 12 | 13 | export const ABOUT_COMPONENTS = [AboutHomeComponent, AboutJoinComponent, AboutSiteComponent, AboutUsComponent]; 14 | -------------------------------------------------------------------------------- /src/app/about/join.component.html: -------------------------------------------------------------------------------- 1 |
2 | 5 |
6 | 7 | 8 |
9 | 如果想和我们一起建设Angular中文社区,请接洽Google 开发技术推广部,我们将给出积极的回应。 10 |
11 | -------------------------------------------------------------------------------- /src/app/about/join.component.scss: -------------------------------------------------------------------------------- 1 | @import "../_shared/styles/common"; 2 | 3 | :host { 4 | display: block; 5 | } 6 | 7 | a { 8 | color: $brand-inverse; 9 | } 10 | 11 | .image { 12 | width: 50vw; 13 | height: 50vw; 14 | display: block; 15 | margin: 20px auto; 16 | } 17 | -------------------------------------------------------------------------------- /src/app/about/join.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'about-join', 5 | templateUrl: './join.component.html', 6 | styleUrls: [ 7 | './join.component.scss' 8 | ] 9 | }) 10 | export class AboutJoinComponent implements OnInit { 11 | constructor() { 12 | } 13 | 14 | ngOnInit() { 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/app/about/showcase/_README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/about/showcase/_README.md -------------------------------------------------------------------------------- /src/app/about/showcase/details.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 |

7 | {{item.title}} 8 |

9 |

10 | 客户:{{item.customer}} 11 |

12 |

13 | 开发:{{item.author}} 14 |

15 |

16 | 发布:{{item.url}} 17 |

18 | 19 |
20 |
21 | -------------------------------------------------------------------------------- /src/app/about/showcase/details.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../_shared/styles/common"; 2 | 3 | :host { 4 | display: block; 5 | } 6 | 7 | .card { 8 | border: none; 9 | .img-circle { 10 | display: block; 11 | margin: 10px auto; 12 | width: 50vw; 13 | height: 50vw; 14 | background: #eee; 15 | box-shadow: 0 0 3px rgba(0, 0, 0, 0.2); 16 | border-radius: 50%; 17 | position: relative; 18 | padding: 40px; 19 | > img { 20 | position: absolute; 21 | display: block; 22 | height: 50%; 23 | width: 50%; 24 | top: 0; 25 | bottom: 0; 26 | left: 0; 27 | right: 0; 28 | margin: auto; 29 | } 30 | } 31 | } 32 | 33 | h2.card-title { 34 | text-align: center; 35 | color: $brand-inverse; 36 | } 37 | 38 | h3.card-title { 39 | text-align: center; 40 | color: $brand-primary; 41 | } 42 | 43 | .card-block { 44 | padding: 0; 45 | } 46 | 47 | .card-link { 48 | display: inline-block; 49 | padding: 0.5rem 0.5rem; 50 | & + .card-link { 51 | margin-left: 0; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/app/about/showcase/details.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, Input} from '@angular/core'; 2 | import {Showcase} from '../../_shared'; 3 | 4 | @Component({ 5 | selector: 'showcase-details', 6 | templateUrl: './details.component.html', 7 | styleUrls: [ 8 | './details.component.scss' 9 | ], 10 | 11 | 12 | }) 13 | export class ShowcaseDetailsComponent implements OnInit { 14 | 15 | @Input() item: Showcase; 16 | 17 | constructor() { 18 | } 19 | 20 | ngOnInit() { 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/app/about/showcase/home.component.html: -------------------------------------------------------------------------------- 1 |
2 | 5 |
6 | 7 | -------------------------------------------------------------------------------- /src/app/about/showcase/home.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/about/showcase/home.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {ActivatedRoute} from '@angular/router'; 3 | import {ShowcaseApi, BasePageComponent, Showcase, MenuItem} from '../../_shared'; 4 | import {Observable} from 'rxjs/Observable'; 5 | 6 | @Component({ 7 | selector: 'showcase-home', 8 | templateUrl: './home.component.html', 9 | styleUrls: [ 10 | './home.component.scss' 11 | ], 12 | 13 | }) 14 | export class ShowcaseHomeComponent extends BasePageComponent { 15 | constructor(activatedRoute: ActivatedRoute, private api: ShowcaseApi) { 16 | super(activatedRoute); 17 | } 18 | 19 | items: Observable; 20 | 21 | reload(params): void { 22 | this.items = this.api.query() 23 | .map(showcaseToMenuItem) 24 | .toArray(); 25 | } 26 | } 27 | 28 | function showcaseToMenuItem(showcase: Showcase): MenuItem { 29 | return { 30 | title: showcase.title, 31 | icon: showcase.picture, 32 | description: `${[showcase.customer, showcase.author].join('&')}`, 33 | url: `/about/showcase/${showcase.id}` 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/app/about/showcase/index.ts: -------------------------------------------------------------------------------- 1 | import {ShowcaseDetailsComponent} from './details.component'; 2 | import {ShowcaseListComponent} from './list.component'; 3 | import {ShowcaseHomeComponent} from './home.component'; 4 | import {ShowcaseShowComponent} from './show.component'; 5 | export * from './details.component'; 6 | export * from './home.component'; 7 | export * from './list.component'; 8 | export * from './show.component'; 9 | 10 | export const SHOWCASE_COMPONENTS = [ShowcaseDetailsComponent, ShowcaseListComponent, ShowcaseHomeComponent, ShowcaseShowComponent]; 11 | -------------------------------------------------------------------------------- /src/app/about/showcase/list.component.html: -------------------------------------------------------------------------------- 1 |
2 | 没有找到符合条件的案例 3 |
4 | 5 | -------------------------------------------------------------------------------- /src/app/about/showcase/list.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/about/showcase/list.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, Input} from '@angular/core'; 2 | import {MenuItem} from '../../_shared'; 3 | 4 | @Component({ 5 | selector: 'showcase-list', 6 | templateUrl: './list.component.html', 7 | styleUrls: [ 8 | './list.component.scss' 9 | ], 10 | 11 | }) 12 | export class ShowcaseListComponent implements OnInit { 13 | constructor() { 14 | } 15 | 16 | @Input() items: MenuItem[]; 17 | 18 | ngOnInit() { 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/app/about/showcase/show.component.html: -------------------------------------------------------------------------------- 1 |
2 | 8 |
9 | 10 | -------------------------------------------------------------------------------- /src/app/about/showcase/show.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/about/showcase/show.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {BasePageComponent, ShowcaseApi, Showcase, matchById} from '../../_shared'; 3 | import {ActivatedRoute} from '@angular/router'; 4 | import {Observable} from 'rxjs/Observable'; 5 | 6 | @Component({ 7 | selector: 'showcase-show', 8 | templateUrl: './show.component.html', 9 | styleUrls: [ 10 | './show.component.scss' 11 | ], 12 | 13 | }) 14 | export class ShowcaseShowComponent extends BasePageComponent { 15 | constructor(activatedRoute: ActivatedRoute, private api: ShowcaseApi) { 16 | super(activatedRoute); 17 | } 18 | 19 | item: Observable; 20 | 21 | reload(params: {id: string}): void { 22 | this.item = this.api.query() 23 | .find(matchById(params.id)) 24 | .do((item: Showcase)=> { 25 | document.title = `${item.title} - Angular中文社区`; 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/app/about/site.component.jade: -------------------------------------------------------------------------------- 1 | header 2 | ol.breadcrumb 3 | li.breadcrumb-item.active 4 | | 中文官网 5 | 6 | h2 站点简介 7 | 8 | p Angular中文官网 9 | a(href="https://angular.cn", target="_blank") https://angular.cn 10 | | 是得到官方认可并由谷歌技术推广部正式运营的中文版Angular官方网站。 11 | 12 | p 它是对angular.io的同步翻译。所谓同步翻译,就是指当官方发布了任何更改时,我们都会将这些更改同步译成中文,以保证资料的时效性和准确性。 13 | 14 | h2 译者简介 15 | 16 | p 本网站有两位主要的翻译者:汪志成和叶志敏。 17 | 18 | ul 19 | li 汪志成是GDE(谷歌开发者专家)和ThoughtWorker,拥有十八年软件开发经验。 20 | li 叶志敏是一位英国留学生,已经在伦敦生活和工作了十年,目前在独立创业。 21 | 22 | p 更多信息参见: 23 | a(href="https://angular.cn/translate/cn/about.html", target="_blank") 这里 24 | 25 | h2 由来 26 | 27 | p Angular 2的整个技术体系相当庞大,随着Angular 2的临近,我们在学习中深感中文资料的匮乏会成为中文学习者的瓶颈。因此,我们下决心对其进行翻译。 28 | p 经过一个月的艰苦努力,我们终于基本翻译完了当时的版本。接着,我们与开发组取得了联系,并得到了项目经理Naomi Black的热情回应。 29 | p 她不但把我们拉进了文档作者的在线交流区,让我们可以直接与原作者交流,而且还帮我们与谷歌技术推广部取得联系,以便更好地在中国推广它。 30 | 31 | h2 社区支持 32 | 33 | p 两个人精力有限,终究无法完美的完成翻译和校对工作。 34 | p 让这个网站趋于完美的,是来自Angular中文社区的志愿者以及来自Github的志愿者。他们提出了很多意见和建议,让我们得以对本网站进行打磨,最终呈献给大家。 35 | 36 | h2 未来 37 | 38 | p 我们还将一如既往的保持同步翻译 —— 虽然这很累。 39 | p 最重要的是,我们将基于本网站来进一步建设中文社区。各位因为本网站来到Angular中文社区,我们希望留住你们,与你们建立更加紧密的联系。 40 | p 同时,我们还会翻译或原创一系列关于Angular 2的书籍,力争全方位的为各位提供帮助。 41 | 42 | h2 谢谢大家! 43 | -------------------------------------------------------------------------------- /src/app/about/site.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/about/site.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'about-site', 5 | templateUrl: './site.component.jade', 6 | styleUrls: [ 7 | './site.component.scss' 8 | ] 9 | }) 10 | export class AboutSiteComponent implements OnInit { 11 | constructor() { 12 | } 13 | 14 | ngOnInit() { 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/app/about/us.component.html: -------------------------------------------------------------------------------- 1 |
2 | 5 |
6 |

社区简介

7 |

Angular中文社区是由Angular开发组支持的大型社区,同时得到了谷歌开发技术推广部的大力支持。

8 |

参见开发组项目经理Naomi 9 | Black、工程总监Brad Green和谷歌开发技术推广部大中华区主管栾跃的致辞

10 |

光辉历程

11 |

Angular中文社区最早源自http://www.angularjs.cn,创始人是严清,主要由网站和QQ群组成。后来由于工作变化,严清不再维护本社区。 12 |

13 |

之后,各位网友自发维护,经过多年的发展,目前在QQ群中已有4000多活跃会员。

14 |

社区理念

15 |

本社区秉承专业、开放、友善的原则,并努力将其落实到行动中。

16 |

社区活动

17 |

目前,我们正组织ng-book2的翻译工作,争取赶在Angular 18 | 2正式发行前定稿。

19 | -------------------------------------------------------------------------------- /src/app/about/us.component.scss: -------------------------------------------------------------------------------- 1 | @import "../_shared/styles/common"; 2 | 3 | :host { 4 | display: block; 5 | } 6 | -------------------------------------------------------------------------------- /src/app/about/us.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'about-us', 5 | templateUrl: './us.component.html', 6 | styleUrls: [ 7 | './us.component.scss' 8 | ] 9 | }) 10 | export class AboutUsComponent implements OnInit { 11 | constructor() { 12 | } 13 | 14 | ngOnInit() { 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import {RouterModule, Routes} from '@angular/router'; 2 | import {NotFoundComponent} from './not-found/not-found.component'; 3 | // import AboutModule from './about/_about.module'; 4 | // import BbsModule from './bbs/_bbs.module'; 5 | // import LibraryModule from './library/_library.module'; 6 | // import UserModule from './user/_user.module'; 7 | import {ChangeTitle} from './_shared/services/change-title'; 8 | import {NgModule} from '@angular/core'; 9 | 10 | const routes: Routes = [ 11 | { 12 | path: '', 13 | canActivateChild: [ChangeTitle], 14 | children: [ 15 | {path: '', pathMatch: 'full', redirectTo: '/user'}, 16 | { 17 | path: 'about', data: {title: '关于我们'}, 18 | loadChildren: './about/_about.module' 19 | }, 20 | { 21 | path: 'bbs', data: {title: '微站论坛'}, 22 | loadChildren: './bbs/_bbs.module' 23 | }, 24 | { 25 | path: 'library', data: {title: '资料中心'}, 26 | loadChildren: './library/_library.module' 27 | }, 28 | { 29 | path: 'user', data: {title: '用户中心'}, 30 | loadChildren: './user/_user.module' 31 | }, 32 | {path: '**', component: NotFoundComponent}, 33 | ] 34 | }, 35 | ]; 36 | 37 | @NgModule({ 38 | imports: [RouterModule.forRoot(routes)], 39 | exports: [RouterModule] 40 | }) 41 | 42 | export class AppRoutingModule { 43 | } 44 | -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 6 |
7 | -------------------------------------------------------------------------------- /src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | main { 6 | padding: 0 1rem; 7 | } 8 | -------------------------------------------------------------------------------- /src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { addProviders, inject } from '@angular/core/testing'; 4 | import { AppComponent } from './app.component'; 5 | 6 | describe('App: UserUi', () => { 7 | beforeEach(() => { 8 | addProviders([AppComponent]); 9 | }); 10 | 11 | it('should create the app', 12 | inject([AppComponent], (app: AppComponent) => { 13 | expect(app).toBeTruthy(); 14 | })); 15 | 16 | it('should have as title \'app works!\'', 17 | inject([AppComponent], (app: AppComponent) => { 18 | })); 19 | }); 20 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.scss'] 7 | }) 8 | export class AppComponent { 9 | } 10 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import {BrowserModule, Title} from '@angular/platform-browser'; 2 | import {NgModule, NgModuleFactoryLoader} from '@angular/core'; 3 | import {FormsModule} from '@angular/forms'; 4 | import {HttpModule} from '@angular/http'; 5 | import {AppComponent} from './app.component'; 6 | import SharedModule from './_shared/_shared.module'; 7 | import {NotFoundComponent} from './not-found/not-found.component'; 8 | import {AppRoutingModule} from './app-routing.module'; 9 | import {RouterModule} from '@angular/router'; 10 | import {LeanNgModuleLoader} from './lean-ng-module-loader'; 11 | 12 | @NgModule({ 13 | declarations: [ 14 | AppComponent, 15 | NotFoundComponent, 16 | ], 17 | imports: [ 18 | BrowserModule, 19 | FormsModule, 20 | HttpModule, 21 | RouterModule, 22 | SharedModule.forRoot(), 23 | AppRoutingModule, 24 | ], 25 | exports: [ 26 | AppComponent 27 | ], 28 | providers: [ 29 | Title 30 | // { provide: NgModuleFactoryLoader, useClass: LeanNgModuleLoader }, 31 | ], 32 | // entryComponents: [AppComponent], 33 | bootstrap: [AppComponent] 34 | }) 35 | export class AppModule { 36 | } 37 | -------------------------------------------------------------------------------- /src/app/bbs/_bbs-routing.module.ts: -------------------------------------------------------------------------------- 1 | import {RouterModule, Routes} from "@angular/router"; 2 | import {BbsHomeComponent} from "./home.component"; 3 | import {ThreadShowComponent} from "./thread/show.component"; 4 | import {ThreadCreateComponent} from "./thread/create.component"; 5 | import {ThreadHomeComponent} from "./thread/home.component"; 6 | import {NgModule} from '@angular/core'; 7 | const routes: Routes = [ 8 | {path: '', pathMatch: 'full', component: BbsHomeComponent,}, 9 | { 10 | path: 'thread', 11 | children: [ 12 | {path: '', pathMatch: 'full', redirectTo: 'mine'}, 13 | {path: 'mine', data: {title: '我的社区'}, pathMatch: 'full', component: ThreadHomeComponent}, 14 | {path: 'hot', data: {title: '最新帖'}, pathMatch: 'full', component: ThreadHomeComponent}, 15 | {path: 'latest', data: {title: '热门帖'}, pathMatch: 'full', component: ThreadHomeComponent}, 16 | {path: 'reward', data: {title: '悬赏贴'}, pathMatch: 'full', component: ThreadHomeComponent}, 17 | {path: 'create', data: {title: '发帖提问'}, pathMatch: 'full', component: ThreadCreateComponent}, 18 | {path: ':id', data: {title: '帖子详情'}, component: ThreadShowComponent}, 19 | ], 20 | }, 21 | ]; 22 | 23 | @NgModule({ 24 | imports: [RouterModule.forChild(routes)], 25 | exports: [RouterModule] 26 | }) 27 | 28 | export class BbsRoutingModule { 29 | } 30 | -------------------------------------------------------------------------------- /src/app/bbs/_bbs.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {CommonModule} from '@angular/common'; 3 | import { BbsRoutingModule} from './_bbs-routing.module'; 4 | import SharedModule from '../_shared/_shared.module'; 5 | import {THREAD_COMPONENTS} from './thread/index'; 6 | import {BbsHomeComponent} from './home.component'; 7 | 8 | @NgModule({ 9 | imports: [ 10 | CommonModule, 11 | SharedModule, 12 | BbsRoutingModule 13 | ], 14 | declarations: [...THREAD_COMPONENTS, BbsHomeComponent] 15 | }) 16 | export default class BbsModule { 17 | } 18 | -------------------------------------------------------------------------------- /src/app/bbs/home.component.html: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 |

5 | 抱歉,本功能仍在开发中,请先访问其它版块。 6 |

7 |

8 | 如咨询技术问题,请到 9 | github 10 | 提问! 11 |

12 |

13 | 我们将尽快上线正式版本,感谢您的关注! 14 |

15 | -------------------------------------------------------------------------------- /src/app/bbs/home.component.scss: -------------------------------------------------------------------------------- 1 | @import "../_shared/styles/common"; 2 | 3 | :host { 4 | display: flex; 5 | flex-direction: column; 6 | padding: 15px; 7 | height: calc(100vh - 48px); 8 | } 9 | 10 | .flex-v { 11 | display: flex; 12 | flex-direction: column; 13 | } 14 | 15 | .flex-auto { 16 | flex: auto; 17 | } 18 | 19 | .avatar { 20 | display: block; 21 | height: 150px; 22 | margin: 0 auto 10px; 23 | } 24 | 25 | .text-primary { 26 | font-size: large; 27 | color: $brand-primary; 28 | } 29 | -------------------------------------------------------------------------------- /src/app/bbs/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'bbs-home', 5 | templateUrl: './home.component.html', 6 | styleUrls: ['./home.component.scss'] 7 | }) 8 | export class BbsHomeComponent implements OnInit { 9 | constructor() { 10 | } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/bbs/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/bbs/index.ts -------------------------------------------------------------------------------- /src/app/bbs/thread/_README.md: -------------------------------------------------------------------------------- 1 | 作者信息 -------------------------------------------------------------------------------- /src/app/bbs/thread/_images/add.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /src/app/bbs/thread/create.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 |
7 | -------------------------------------------------------------------------------- /src/app/bbs/thread/create.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../_shared/styles/common"; 2 | 3 | :host { 4 | } 5 | 6 | .editor { 7 | min-height: 300px; 8 | border: 1px solid $gray-lighter; 9 | } 10 | -------------------------------------------------------------------------------- /src/app/bbs/thread/create.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Http } from '@angular/http'; 3 | import { DomSanitizer } from '@angular/platform-browser'; 4 | 5 | @Component({ 6 | selector: 'thread-create', 7 | templateUrl: './create.component.html', 8 | styleUrls: [ 9 | './create.component.scss' 10 | ] 11 | }) 12 | export class ThreadCreateComponent implements OnInit { 13 | html; 14 | constructor(private http: Http, private sanitizer: DomSanitizer) { 15 | } 16 | 17 | ngOnInit() { 18 | } 19 | update(text) { 20 | this.html = text; // this.sanitizer.bypassSecurityTrustHtml(text); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/app/bbs/thread/details.component.html: -------------------------------------------------------------------------------- 1 |

2 | {{item.title}} 3 | 4 | {{author}} 5 | 6 |

7 | 8 | 题图 9 | 10 | -------------------------------------------------------------------------------- /src/app/bbs/thread/details.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../_shared/styles/common"; 2 | 3 | :host { 4 | display: block; 5 | } 6 | 7 | .major-picture { 8 | width: 50vw; 9 | display: block; 10 | margin: auto; 11 | } 12 | 13 | small { 14 | line-height: 1.5rem; 15 | vertical-align: bottom; 16 | } 17 | 18 | .tag { 19 | margin-right: 0.5rem; 20 | } 21 | -------------------------------------------------------------------------------- /src/app/bbs/thread/details.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, Input} from '@angular/core'; 2 | import {Thread} from '../../_shared'; 3 | 4 | @Component({ 5 | selector: 'thread-details', 6 | templateUrl: './details.component.html', 7 | styleUrls: [ 8 | './details.component.scss' 9 | ], 10 | 11 | 12 | }) 13 | export class ThreadDetailsComponent implements OnInit { 14 | @Input() item: Thread; 15 | 16 | constructor() { 17 | } 18 | 19 | ngOnInit() { 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/app/bbs/thread/home.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/app/bbs/thread/home.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | padding-top: 1rem; 4 | } 5 | -------------------------------------------------------------------------------- /src/app/bbs/thread/home.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {ActivatedRoute} from '@angular/router'; 3 | import {Observable} from 'rxjs/Observable'; 4 | import {ThreadApi, Thread} from '../../_shared'; 5 | 6 | @Component({ 7 | selector: 'thread-home', 8 | templateUrl: './home.component.html', 9 | styleUrls: [ 10 | './home.component.scss' 11 | ], 12 | 13 | }) 14 | export class ThreadHomeComponent { 15 | constructor(private activatedRoute: ActivatedRoute, private api: ThreadApi) { 16 | } 17 | 18 | items: Observable; 19 | 20 | ngOnInit() { 21 | const url = this.activatedRoute.snapshot.url[0]; 22 | this.items = this.api.query(url.path) 23 | .toArray(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/app/bbs/thread/index.ts: -------------------------------------------------------------------------------- 1 | import {ThreadDetailsComponent} from './details.component'; 2 | import {ThreadListComponent} from './list.component'; 3 | import {ThreadHomeComponent} from './home.component'; 4 | import {ThreadShowComponent} from './show.component'; 5 | import {ThreadCreateComponent} from './create.component'; 6 | import {BbsThreadNavComponent} from './nav.component'; 7 | export * from './details.component'; 8 | export * from './home.component'; 9 | export * from './list.component'; 10 | export * from './show.component'; 11 | export * from './create.component'; 12 | 13 | export const THREAD_COMPONENTS = [ThreadDetailsComponent, ThreadListComponent, ThreadHomeComponent, ThreadShowComponent, ThreadCreateComponent, BbsThreadNavComponent]; 14 | -------------------------------------------------------------------------------- /src/app/bbs/thread/list.component.html: -------------------------------------------------------------------------------- 1 |
2 | 没有相关主题 3 |
4 | 9 | -------------------------------------------------------------------------------- /src/app/bbs/thread/list.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/bbs/thread/list.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, Input} from '@angular/core'; 2 | import {Thread} from '../../_shared'; 3 | 4 | @Component({ 5 | selector: 'thread-list', 6 | templateUrl: './list.component.html', 7 | styleUrls: [ 8 | './list.component.scss' 9 | ] 10 | }) 11 | export class ThreadListComponent implements OnInit { 12 | constructor() { 13 | } 14 | 15 | @Input() items: Thread[]; 16 | 17 | ngOnInit() { 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/app/bbs/thread/nav.component.html: -------------------------------------------------------------------------------- 1 | 2 | 发帖 3 | 4 | 10 | -------------------------------------------------------------------------------- /src/app/bbs/thread/nav.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../_shared/styles/common"; 2 | 3 | :host { 4 | display: block; 5 | margin-bottom: 1rem; 6 | } 7 | 8 | .nav.nav-simple { 9 | .nav-link { 10 | padding: 0.5em 0.25em 0.1em; 11 | } 12 | .nav-item { 13 | width: 25%; 14 | .nav-link { 15 | color: $gray-light; 16 | &.active { 17 | border-bottom: 1px solid $brand-primary; 18 | color: $brand-primary; 19 | } 20 | } 21 | } 22 | } 23 | 24 | .btn.btn-secondary { 25 | color: $gray-lightest; 26 | } 27 | -------------------------------------------------------------------------------- /src/app/bbs/thread/nav.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'bbs-thread-nav', 5 | templateUrl: './nav.component.html', 6 | styleUrls: [ 7 | './nav.component.scss' 8 | ], 9 | 10 | }) 11 | export class BbsThreadNavComponent implements OnInit { 12 | constructor() { 13 | } 14 | 15 | ngOnInit() { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/app/bbs/thread/show.component.html: -------------------------------------------------------------------------------- 1 |
2 | 8 |
9 | 10 | -------------------------------------------------------------------------------- /src/app/bbs/thread/show.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/bbs/thread/show.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { ThreadApi, Thread, BasePageComponent, matchById } from '../../_shared'; 3 | import { ActivatedRoute } from '@angular/router'; 4 | import { Observable } from 'rxjs/Observable'; 5 | 6 | @Component({ 7 | selector: 'thread-show', 8 | templateUrl: './show.component.html', 9 | styleUrls: [ 10 | './show.component.scss' 11 | ], 12 | 13 | }) 14 | export class ThreadShowComponent extends BasePageComponent { 15 | constructor(private api: ThreadApi, activatedRoute: ActivatedRoute) { 16 | super(activatedRoute); 17 | } 18 | 19 | item: Observable; 20 | 21 | reload(params: { id: string }) { 22 | this.item = this.api.query('') 23 | .find(matchById(params.id)) 24 | .do((item: Thread) => { 25 | document.title = `${item.title} - Angular中文社区`; 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/app/environments/environment.dev.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: false 3 | }; 4 | -------------------------------------------------------------------------------- /src/app/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /src/app/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // The file for the current environment will overwrite this one during build. 2 | // Different environments can be found in ./environment.{dev|prod}.ts, and 3 | // you can create your own and use it with the --env flag. 4 | // The build system defaults to the dev environment. 5 | 6 | export const environment = { 7 | production: false 8 | }; 9 | -------------------------------------------------------------------------------- /src/app/index.ts: -------------------------------------------------------------------------------- 1 | // export * from './environments/environment'; 2 | // export * from './app.component'; 3 | // export * from './app.module'; 4 | -------------------------------------------------------------------------------- /src/app/lean-ng-module-loader.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, NgModuleFactory, NgModuleFactoryLoader, Compiler, Type } from '@angular/core'; 2 | 3 | class LoaderCallback { 4 | constructor(public callback) { 5 | } 6 | } 7 | 8 | export let load: any = (callback: Function) => { 9 | return new LoaderCallback(callback); 10 | }; 11 | 12 | /** 13 | * A lean & pure module factory loader for simply load another module which needn't any async feature 14 | * NgModuleFactoryLoader that uses Promise to load NgModule type and then compiles them. 15 | * @experimental 16 | */ 17 | @Injectable() 18 | export class LeanNgModuleLoader implements NgModuleFactoryLoader { 19 | constructor(private compiler: Compiler) { 20 | } 21 | 22 | 23 | load(data): Promise> { 24 | return Promise.resolve(data) 25 | .then((type: any) => checkNotEmpty(type, '', '')) 26 | .then((type: any) => this.compiler.compileModuleAsync(type)); 27 | } 28 | } 29 | 30 | function checkNotEmpty(value: any, modulePath: string, exportName: string): any { 31 | if (!value) { 32 | throw new Error(`Cannot find '${exportName}' in '${modulePath}'`); 33 | } 34 | return value; 35 | } 36 | -------------------------------------------------------------------------------- /src/app/library/_README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/library/_README.md -------------------------------------------------------------------------------- /src/app/library/_images/articles.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | articles 6 | Created with Sketch. 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/app/library/_images/external.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | external 6 | Created with Sketch. 7 | 8 | 9 | 10 | 13 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/app/library/_images/news.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | news 6 | Created with Sketch. 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/app/library/_images/wechat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/library/_images/wechat.jpg -------------------------------------------------------------------------------- /src/app/library/_library.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {CommonModule} from '@angular/common'; 3 | import {LibraryHomeComponent} from './home.component'; 4 | import {LibraryRoutingModule} from './_library-routing.module'; 5 | import SharedModule from '../_shared/_shared.module'; 6 | import {ARTICLE_COMPONENTS} from './article/index'; 7 | import {AUTHOR_COMPONENTS} from './author/index'; 8 | import {COLUMN_COMPONENTS} from './column/index'; 9 | import {NEWS_COMPONENTS} from './news/index'; 10 | import {PARTNER_COMPONENTS} from './partner/index'; 11 | import {RESOURCE_COMPONENTS} from './resource/index'; 12 | 13 | @NgModule({ 14 | imports: [ 15 | CommonModule, 16 | SharedModule, 17 | LibraryRoutingModule, 18 | ], 19 | declarations: [ 20 | LibraryHomeComponent, 21 | ...ARTICLE_COMPONENTS, 22 | ...AUTHOR_COMPONENTS, 23 | ...COLUMN_COMPONENTS, 24 | ...NEWS_COMPONENTS, 25 | ...PARTNER_COMPONENTS, 26 | ...RESOURCE_COMPONENTS, 27 | ], 28 | }) 29 | export default class LibraryModule { 30 | } 31 | -------------------------------------------------------------------------------- /src/app/library/article/_README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/library/article/_README.md -------------------------------------------------------------------------------- /src/app/library/article/_images/chevron-left.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/app/library/article/_images/chevron-right.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/app/library/article/_images/devrel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/library/article/_images/devrel.png -------------------------------------------------------------------------------- /src/app/library/article/details.component.html: -------------------------------------------------------------------------------- 1 |

{{item.title}}

2 | 3 |

4 | {{author}} 5 | [译]{{translator}} 7 | 8 | 9 | 10 | 11 | 12 |

13 | 14 |

15 | 点此查看原文 16 |

17 | 18 |
19 | 20 |
21 | 22 | 23 | 24 |
25 |
26 |
27 | 微信二维码 28 |
29 |
30 |

31 | Angular中文社区
32 | agnularcn 33 |

34 |

35 | 长按识别二维码关注我们 36 |
37 | 或拷贝 38 | 39 | 这个链接 40 | 41 | 推荐我们 42 |

43 |
44 | 45 |
46 |
47 |
48 | 我们属于谷歌开发技术推广部, 49 | 50 | 点此关注 51 | 52 |
53 |
54 | -------------------------------------------------------------------------------- /src/app/library/article/details.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../_shared/styles/common"; 2 | 3 | :host { 4 | display: block; 5 | } 6 | 7 | h2 { 8 | padding-bottom: 6px; 9 | border-bottom: 1px solid $brand-secondary; 10 | } 11 | 12 | blockquote { 13 | color: $gray-light; 14 | } 15 | 16 | .media { 17 | text-align: center; 18 | .media-object { 19 | height: 128px; 20 | max-width: 128px; 21 | margin: -8px; 22 | } 23 | .media-heading { 24 | position: relative; 25 | padding: 1rem 0; 26 | &::before, &::after { 27 | position: absolute; 28 | content: ' '; 29 | display: inline-block; 30 | width: 2em; 31 | height: 2em; 32 | top: 0; 33 | bottom: 0; 34 | margin: auto; 35 | color: $gray; 36 | } 37 | &::before { 38 | left: 0; 39 | background: url(./_images/chevron-left.svg) no-repeat left center; 40 | } 41 | &::after { 42 | right: 0; 43 | background: url(./_images/chevron-right.svg) no-repeat right center; 44 | } 45 | } 46 | p { 47 | margin-bottom: 0; 48 | font-size: 14px; 49 | color: $gray; 50 | } 51 | } 52 | 53 | footer { 54 | border: 2px solid $brand-warning; 55 | border-radius: 2px; 56 | padding: 1rem; 57 | margin: 2rem 0; 58 | } 59 | 60 | .block-center { 61 | margin-top: 30px; 62 | display: block; 63 | max-width: 100%; 64 | } 65 | -------------------------------------------------------------------------------- /src/app/library/article/details.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, Input} from '@angular/core'; 2 | import {Article} from '../../_shared'; 3 | 4 | @Component({ 5 | selector: 'article-details', 6 | templateUrl: './details.component.html', 7 | styleUrls: [ 8 | './details.component.scss' 9 | ], 10 | 11 | }) 12 | export class ArticleDetailsComponent implements OnInit { 13 | @Input() item: Article; 14 | 15 | constructor() { 16 | } 17 | 18 | ngOnInit() { 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/app/library/article/home.component.html: -------------------------------------------------------------------------------- 1 |
2 | 5 |
6 | 7 | -------------------------------------------------------------------------------- /src/app/library/article/home.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/library/article/home.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {BasePageComponent, ArticleApi, Article} from '../../_shared'; 3 | import {ActivatedRoute} from '@angular/router'; 4 | import {Observable} from 'rxjs/Observable'; 5 | 6 | @Component({ 7 | selector: 'article-home', 8 | templateUrl: './home.component.html', 9 | styleUrls: [ 10 | './home.component.scss' 11 | ], 12 | 13 | }) 14 | export class ArticleHomeComponent extends BasePageComponent { 15 | constructor(activatedRoute: ActivatedRoute, private api: ArticleApi) { 16 | super(activatedRoute); 17 | } 18 | 19 | items: Observable; 20 | 21 | reload(params: {author: string, tag: string, column: string}): void { 22 | this.items = this.api.query() 23 | .filter(matchByAuthor(params.author)) 24 | .filter(matchByTag(params.tag)) 25 | .filter(matchByColumn(params.column)) 26 | .toArray(); 27 | } 28 | } 29 | 30 | function matchByAuthor(author: string): (item)=>boolean { 31 | return (item)=> { 32 | return !author || item.authors.indexOf(author) !== -1 33 | } 34 | } 35 | 36 | function matchByTag(tag: string): (item)=>boolean { 37 | return (item)=> { 38 | return !tag || item.tags && item.tags.indexOf(tag) !== -1 39 | } 40 | } 41 | 42 | function matchByColumn(column: string): (item)=>boolean { 43 | return (item)=> { 44 | return !column || item.column === column 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/app/library/article/index.ts: -------------------------------------------------------------------------------- 1 | import {ArticleDetailsComponent} from './details.component'; 2 | import {ArticleListComponent} from './list.component'; 3 | import {ArticleHomeComponent} from './home.component'; 4 | import {ArticleShowComponent} from './show.component'; 5 | export * from './details.component'; 6 | export * from './home.component'; 7 | export * from './list.component'; 8 | export * from './show.component'; 9 | 10 | export const ARTICLE_COMPONENTS = [ArticleDetailsComponent, ArticleListComponent, ArticleHomeComponent, ArticleShowComponent]; 11 | -------------------------------------------------------------------------------- /src/app/library/article/list.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 没有找到符合条件的文章 4 |
5 | 6 | {{item.title}} [{{item.authors}}] 7 | 8 |
9 | -------------------------------------------------------------------------------- /src/app/library/article/list.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/library/article/list.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, Input} from '@angular/core'; 2 | import {Article} from '../../_shared'; 3 | 4 | @Component({ 5 | selector: 'article-list', 6 | templateUrl: './list.component.html', 7 | styleUrls: [ 8 | './list.component.scss' 9 | ] 10 | }) 11 | export class ArticleListComponent { 12 | constructor() { 13 | } 14 | 15 | @Input() items: Article[]; 16 | } 17 | -------------------------------------------------------------------------------- /src/app/library/article/show.component.html: -------------------------------------------------------------------------------- 1 |
2 | 8 |
9 | 10 | 11 | -------------------------------------------------------------------------------- /src/app/library/article/show.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/library/article/show.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {Article, ArticleApi, matchById, BasePageComponent} from '../../_shared'; 3 | import {ActivatedRoute} from '@angular/router'; 4 | import {Observable} from 'rxjs/Observable'; 5 | 6 | @Component({ 7 | selector: 'article-show', 8 | templateUrl: './show.component.html', 9 | styleUrls: [ 10 | './show.component.scss' 11 | ], 12 | 13 | }) 14 | export class ArticleShowComponent extends BasePageComponent { 15 | constructor(private api: ArticleApi, activatedRoute: ActivatedRoute) { 16 | super(activatedRoute); 17 | } 18 | 19 | item: Observable
; 20 | 21 | reload(params: {id: string}) { 22 | this.item = this.api.query() 23 | .find(matchById(params.id)) 24 | .do((item: Article)=> { 25 | document.title = `${item.title} - Angular中文社区`; 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/app/library/author/_README.md: -------------------------------------------------------------------------------- 1 | 作者信息 -------------------------------------------------------------------------------- /src/app/library/author/details.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |

5 | {{item.name}} 6 |

7 |

{{item.bio}}

8 | 9 |
10 |

11 | 主页 12 | 专栏 13 | 文章 14 | 书籍 15 |

16 |
17 |
18 | -------------------------------------------------------------------------------- /src/app/library/author/details.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../_shared/styles/common"; 2 | 3 | :host { 4 | display: block; 5 | } 6 | 7 | .card { 8 | border: none; 9 | .img-circle { 10 | display: block; 11 | margin: 10px auto; 12 | width: 50%; 13 | border-radius: 50%; 14 | border: 1px solid $gray-lighter; 15 | } 16 | } 17 | 18 | h2.card-title { 19 | text-align: center; 20 | color: $brand-inverse; 21 | } 22 | 23 | h3.card-title { 24 | text-align: center; 25 | color: $brand-primary; 26 | } 27 | 28 | .card-block { 29 | padding: 0; 30 | } 31 | 32 | .card-link { 33 | display: inline-block; 34 | padding: 0.5rem 1rem; 35 | & + .card-link { 36 | margin-left: 0; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/app/library/author/details.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, Input} from '@angular/core'; 2 | import {Author} from '../../_shared'; 3 | 4 | @Component({ 5 | selector: 'author-details', 6 | templateUrl: './details.component.html', 7 | styleUrls: [ 8 | './details.component.scss' 9 | ], 10 | 11 | 12 | }) 13 | export class AuthorDetailsComponent implements OnInit { 14 | 15 | @Input() item: Author; 16 | 17 | constructor() { 18 | } 19 | 20 | ngOnInit() { 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/app/library/author/home.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/app/library/author/home.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/library/author/home.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {AuthorApi, Author, BasePageComponent, matchById, MenuItem} from '../../_shared'; 3 | import {ActivatedRoute} from '@angular/router'; 4 | import {Observable} from 'rxjs/Observable'; 5 | 6 | @Component({ 7 | selector: 'author-home', 8 | templateUrl: './home.component.html', 9 | styleUrls: [ 10 | './home.component.scss' 11 | ], 12 | 13 | }) 14 | export class AuthorHomeComponent extends BasePageComponent { 15 | constructor(activatedRoute: ActivatedRoute, private api: AuthorApi) { 16 | super(activatedRoute); 17 | } 18 | 19 | items: Observable; 20 | 21 | reload(): void { 22 | this.items = this.api.queryAll() 23 | .map(authors => authors.map(authorToMenuItem)); 24 | } 25 | } 26 | 27 | function authorToMenuItem(author: Author): MenuItem { 28 | return { 29 | icon: author.avatar, 30 | description: author.bio, 31 | title: author.name, 32 | url: `./${author.id}` 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/app/library/author/index.ts: -------------------------------------------------------------------------------- 1 | import {AuthorDetailsComponent} from './details.component'; 2 | import {AuthorListComponent} from './list.component'; 3 | import {AuthorHomeComponent} from './home.component'; 4 | import {AuthorShowComponent} from './show.component'; 5 | export * from './details.component'; 6 | export * from './home.component'; 7 | export * from './list.component'; 8 | export * from './show.component'; 9 | 10 | export const AUTHOR_COMPONENTS = [AuthorDetailsComponent, AuthorListComponent, AuthorHomeComponent, AuthorShowComponent]; 11 | -------------------------------------------------------------------------------- /src/app/library/author/list.component.html: -------------------------------------------------------------------------------- 1 |
2 | 没有找到符合条件的作者 3 |
4 | 5 | -------------------------------------------------------------------------------- /src/app/library/author/list.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/library/author/list.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, Input} from '@angular/core'; 2 | import {MenuItem} from '../../_shared'; 3 | 4 | @Component({ 5 | selector: 'author-list', 6 | templateUrl: './list.component.html', 7 | styleUrls: [ 8 | './list.component.scss' 9 | ], 10 | 11 | }) 12 | export class AuthorListComponent implements OnInit { 13 | constructor() { 14 | } 15 | 16 | @Input() items: MenuItem[]; 17 | 18 | ngOnInit() { 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/app/library/author/show.component.html: -------------------------------------------------------------------------------- 1 |
2 | 8 |
9 | 10 | -------------------------------------------------------------------------------- /src/app/library/author/show.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/library/author/show.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {AuthorApi, Author, BasePageComponent, matchById} from '../../_shared'; 3 | import {ActivatedRoute} from '@angular/router'; 4 | import {Observable} from 'rxjs/Observable'; 5 | 6 | @Component({ 7 | selector: 'author-show', 8 | templateUrl: './show.component.html', 9 | styleUrls: [ 10 | './show.component.scss' 11 | ], 12 | 13 | }) 14 | export class AuthorShowComponent extends BasePageComponent { 15 | constructor(private api: AuthorApi, activatedRoute: ActivatedRoute) { 16 | super(activatedRoute); 17 | } 18 | 19 | item: Observable; 20 | 21 | reload(params: {id: string}) { 22 | this.item = this.api.queryOne(params) 23 | .do((item: Author)=> { 24 | // 根据api.query,如果没找到的话, 25 | // 会返回一个假的author, spectreAuthor 26 | // 所以就不用`if(item)`来检查item是否是undefined了 27 | // 这是权宜之计,正常情况下,没找到的话应该转到404 28 | document.title = `${item.name} - 作者 - Angular中文社区`; 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/app/library/column/_README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/library/column/_README.md -------------------------------------------------------------------------------- /src/app/library/column/details.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |

5 | {{item.name}} 6 | 7 | [ 8 | {{author}} 10 | ] 11 | 12 |

13 |

{{item.bio}}

14 | 15 |
16 |

17 | {{tag}} 19 |

20 |
21 |
22 | -------------------------------------------------------------------------------- /src/app/library/column/details.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../_shared/styles/common"; 2 | 3 | :host { 4 | display: block; 5 | } 6 | 7 | .card { 8 | border: none; 9 | .img-circle { 10 | display: block; 11 | margin: 10px auto; 12 | width: 50%; 13 | border-radius: 50%; 14 | border: 1px solid $gray-lighter; 15 | } 16 | } 17 | 18 | .card-title { 19 | color: $brand-inverse; 20 | small { 21 | a { 22 | &:not(:last-child) { 23 | margin-right: 1rem; 24 | } 25 | } 26 | } 27 | } 28 | 29 | .card-text { 30 | color: $gray-light; 31 | } 32 | 33 | .card-block { 34 | padding: 0; 35 | } 36 | 37 | .card-link { 38 | display: inline-block; 39 | padding: 0.5rem; 40 | & + .card-link { 41 | margin-left: 0; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/app/library/column/details.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, Input} from '@angular/core'; 2 | import {Column} from '../../_shared'; 3 | 4 | @Component({ 5 | selector: 'column-details', 6 | templateUrl: './details.component.html', 7 | styleUrls: [ 8 | './details.component.scss' 9 | ], 10 | 11 | 12 | }) 13 | export class ColumnDetailsComponent implements OnInit { 14 | constructor() { 15 | } 16 | 17 | @Input() item: Column; 18 | 19 | ngOnInit() { 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/app/library/column/home.component.html: -------------------------------------------------------------------------------- 1 |
2 | 5 |
6 | 7 | -------------------------------------------------------------------------------- /src/app/library/column/home.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/library/column/home.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {ActivatedRoute} from '@angular/router'; 3 | import {Observable} from 'rxjs/Observable'; 4 | import {Column, BasePageComponent, matchById, ColumnApi, MenuItem} from '../../_shared'; 5 | 6 | @Component({ 7 | selector: 'column-home', 8 | templateUrl: './home.component.html', 9 | styleUrls: [ 10 | './home.component.scss' 11 | ], 12 | 13 | }) 14 | export class ColumnHomeComponent extends BasePageComponent { 15 | constructor(activatedRoute: ActivatedRoute, private api: ColumnApi) { 16 | super(activatedRoute); 17 | } 18 | 19 | items: Observable; 20 | 21 | reload(params: {id: string}) { 22 | this.items = this.api.query() 23 | .filter(matchById(params.id)) 24 | .map(columnToMenu) 25 | .toArray(); 26 | } 27 | } 28 | 29 | function columnToMenu(column: Column): MenuItem { 30 | return { 31 | icon: column.avatar, 32 | description: column.bio, 33 | title: column.name, 34 | url: `./${column.id}` 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/app/library/column/index.ts: -------------------------------------------------------------------------------- 1 | import {ColumnDetailsComponent} from './details.component'; 2 | import {ColumnListComponent} from './list.component'; 3 | import {ColumnHomeComponent} from './home.component'; 4 | import {ColumnShowComponent} from './show.component'; 5 | export * from './details.component'; 6 | export * from './home.component'; 7 | export * from './list.component'; 8 | export * from './show.component'; 9 | 10 | export const COLUMN_COMPONENTS = [ColumnDetailsComponent, ColumnListComponent, ColumnHomeComponent, ColumnShowComponent]; 11 | -------------------------------------------------------------------------------- /src/app/library/column/list.component.html: -------------------------------------------------------------------------------- 1 |
2 | 没有找到符合条件的专栏 3 |
4 | 5 | -------------------------------------------------------------------------------- /src/app/library/column/list.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/library/column/list.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, Input} from '@angular/core'; 2 | import {Column} from '../../_shared'; 3 | 4 | @Component({ 5 | selector: 'column-list', 6 | templateUrl: './list.component.html', 7 | styleUrls: [ 8 | './list.component.scss' 9 | ], 10 | 11 | }) 12 | export class ColumnListComponent implements OnInit { 13 | constructor() { 14 | } 15 | 16 | @Input() items: Column[]; 17 | 18 | ngOnInit() { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/app/library/column/show.component.html: -------------------------------------------------------------------------------- 1 |
2 | 8 |
9 | 10 | 11 | -------------------------------------------------------------------------------- /src/app/library/column/show.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/library/column/show.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {BasePageComponent, Column, matchById, ColumnApi} from '../../_shared'; 3 | import {ActivatedRoute} from '@angular/router'; 4 | import {Observable} from 'rxjs/Observable'; 5 | 6 | @Component({ 7 | selector: 'column-show', 8 | templateUrl: './show.component.html', 9 | styleUrls: [ 10 | './show.component.scss' 11 | ], 12 | 13 | }) 14 | export class ColumnShowComponent extends BasePageComponent { 15 | constructor(activateRoute: ActivatedRoute, private api: ColumnApi) { 16 | super(activateRoute); 17 | } 18 | 19 | item: Observable; 20 | 21 | reload(params: {id: string}): void { 22 | this.item = this.api.query() 23 | .find(matchById(params.id)) 24 | .do((item: Column)=> { 25 | document.title = `${item.name} - Angular中文社区`; 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/app/library/home.component.html: -------------------------------------------------------------------------------- 1 |
2 | 点此投稿,共同为社区做贡献 3 |
4 | 5 | -------------------------------------------------------------------------------- /src/app/library/home.component.scss: -------------------------------------------------------------------------------- 1 | @import "../_shared/styles/common"; 2 | 3 | :host { 4 | display: block; 5 | padding-top: 1rem; 6 | } 7 | 8 | -------------------------------------------------------------------------------- /src/app/library/home.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {MenuItem} from '../_shared'; 3 | 4 | @Component({ 5 | selector: 'library-home', 6 | templateUrl: './home.component.html', 7 | styleUrls: [ 8 | './home.component.scss' 9 | ], 10 | 11 | }) 12 | export class LibraryHomeComponent implements OnInit { 13 | constructor() { 14 | } 15 | 16 | ngOnInit() { 17 | } 18 | 19 | items: MenuItem[] = [ 20 | { 21 | title: '精品文章', 22 | description: '技巧、实践、剖析、案例', 23 | icon: require('./_images/articles.svg'), 24 | url: './article' 25 | }, 26 | { 27 | title: '技术专栏', 28 | description: '由一线技术专家撰写的专栏', 29 | icon: require('./_images/professional.svg'), 30 | url: './column' 31 | }, 32 | { 33 | title: '前沿观察', 34 | description: '来自国内外的重要新闻', 35 | icon: require('./_images/news.svg'), 36 | url: './news' 37 | }, 38 | { 39 | title: '资源雷达', 40 | description: '第三方资源的推荐与评测', 41 | icon: require('./_images/radar.svg'), 42 | url: './resource' 43 | }, 44 | { 45 | title: '友情链接', 46 | description: '与我们并肩作战的友军站点', 47 | icon: require('./_images/external.svg'), 48 | url: './partner' 49 | } 50 | ]; 51 | } 52 | -------------------------------------------------------------------------------- /src/app/library/news/_README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/library/news/_README.md -------------------------------------------------------------------------------- /src/app/library/news/details.component.html: -------------------------------------------------------------------------------- 1 |

{{item.title}}

2 | 3 |

4 | {{author}} 5 | [译]{{translator}} 7 | 8 | 9 | 10 | 11 | 12 |

13 | 14 |

15 | {{item.originalUrl}} 16 |

17 | 18 |
19 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /src/app/library/news/details.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/library/news/details.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, Input} from '@angular/core'; 2 | import {Article} from '../../_shared'; 3 | 4 | @Component({ 5 | selector: 'news-details', 6 | templateUrl: './details.component.html', 7 | styleUrls: [ 8 | './details.component.scss' 9 | ], 10 | 11 | }) 12 | export class NewsDetailsComponent implements OnInit { 13 | 14 | @Input() item: Article; 15 | 16 | constructor() { 17 | } 18 | 19 | ngOnInit() { 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/app/library/news/home.component.html: -------------------------------------------------------------------------------- 1 |
2 | 5 |
6 | 7 | -------------------------------------------------------------------------------- /src/app/library/news/home.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/library/news/home.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {ActivatedRoute} from '@angular/router'; 3 | import {NewsApi, BasePageComponent, Article, MenuItem} from '../../_shared'; 4 | import {Observable} from 'rxjs/Observable'; 5 | 6 | @Component({ 7 | selector: 'news-home', 8 | templateUrl: './home.component.html', 9 | styleUrls: [ 10 | './home.component.scss' 11 | ], 12 | 13 | }) 14 | export class NewsHomeComponent extends BasePageComponent { 15 | constructor(activatedRoute: ActivatedRoute, private api: NewsApi) { 16 | super(activatedRoute); 17 | } 18 | 19 | items: Observable; 20 | 21 | reload(params): void { 22 | this.items = this.api.query() 23 | .map(newsToMenuItem) 24 | .toArray(); 25 | } 26 | } 27 | 28 | function newsToMenuItem(news: Article): MenuItem { 29 | return { 30 | title: news.title, 31 | icon: news.image, 32 | description: news.summary, 33 | url: `/library/news/${news.id}` 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/app/library/news/index.ts: -------------------------------------------------------------------------------- 1 | import {NewsDetailsComponent} from './details.component'; 2 | import {NewsListComponent} from './list.component'; 3 | import {NewsHomeComponent} from './home.component'; 4 | import {NewsShowComponent} from './show.component'; 5 | import {NewsTrendComponent} from './trend.component'; 6 | export * from './details.component'; 7 | export * from './home.component'; 8 | export * from './list.component'; 9 | export * from './show.component'; 10 | 11 | export const NEWS_COMPONENTS = [NewsDetailsComponent, NewsListComponent, NewsHomeComponent, NewsShowComponent, NewsTrendComponent]; 12 | -------------------------------------------------------------------------------- /src/app/library/news/list.component.html: -------------------------------------------------------------------------------- 1 |
2 | 没有找到符合条件的新闻 3 |
4 | 5 | -------------------------------------------------------------------------------- /src/app/library/news/list.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/library/news/list.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, Input} from '@angular/core'; 2 | import {MenuItem} from '../../_shared'; 3 | 4 | @Component({ 5 | selector: 'news-list', 6 | templateUrl: './list.component.html', 7 | styleUrls: [ 8 | './list.component.scss' 9 | ], 10 | 11 | }) 12 | export class NewsListComponent implements OnInit { 13 | constructor() { 14 | } 15 | 16 | @Input() items: MenuItem[]; 17 | 18 | ngOnInit() { 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/app/library/news/show.component.html: -------------------------------------------------------------------------------- 1 |
2 | 8 |
9 | 10 | -------------------------------------------------------------------------------- /src/app/library/news/show.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/library/news/show.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {BasePageComponent, NewsApi, Article, matchById} from '../../_shared'; 3 | import {ActivatedRoute} from '@angular/router'; 4 | import {Observable} from 'rxjs/Observable'; 5 | 6 | @Component({ 7 | selector: 'news-show', 8 | templateUrl: './show.component.html', 9 | styleUrls: [ 10 | './show.component.scss' 11 | ], 12 | 13 | }) 14 | export class NewsShowComponent extends BasePageComponent { 15 | constructor(activatedRoute: ActivatedRoute, private api: NewsApi) { 16 | super(activatedRoute); 17 | } 18 | 19 | item: Observable
; 20 | 21 | reload(params: {id: string}): void { 22 | this.item = this.api.query() 23 | .find(matchById(params.id)) 24 | .do((item: Article)=> { 25 | document.title = `${item.title} - Angular中文社区`; 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/app/library/news/trend.component.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/library/news/trend.component.html -------------------------------------------------------------------------------- /src/app/library/news/trend.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/library/news/trend.component.scss -------------------------------------------------------------------------------- /src/app/library/news/trend.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'news-trend', 5 | templateUrl: './trend.component.html', 6 | styleUrls: [ 7 | './trend.component.scss' 8 | ] 9 | }) 10 | export class NewsTrendComponent implements OnInit { 11 | constructor() { 12 | } 13 | 14 | ngOnInit() { 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/app/library/partner/_README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/library/partner/_README.md -------------------------------------------------------------------------------- /src/app/library/partner/details.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |

5 | {{item.name}} 6 |

7 | 8 |
9 |
10 | 首页: 11 | 12 | {{item.homepage}} 13 | 14 | 15 |
16 |
17 |
18 | -------------------------------------------------------------------------------- /src/app/library/partner/details.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../_shared/styles/common"; 2 | 3 | :host { 4 | display: block; 5 | } 6 | 7 | .card { 8 | border: none; 9 | .card-img-top { 10 | display: block; 11 | margin: 10px auto; 12 | width: 50%; 13 | border-radius: 50%; 14 | border: 1px solid $gray-lighter; 15 | } 16 | } 17 | 18 | .card-title { 19 | color: $brand-inverse; 20 | small { 21 | a { 22 | &:not(:last-child) { 23 | margin-right: 1rem; 24 | } 25 | } 26 | } 27 | } 28 | 29 | .card-text { 30 | color: $gray-light; 31 | } 32 | 33 | .card-block { 34 | padding: 0; 35 | } 36 | 37 | .card-link { 38 | display: inline-block; 39 | padding: 0.5rem; 40 | & + .card-link { 41 | margin-left: 0; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/app/library/partner/details.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, Input} from '@angular/core'; 2 | import {Partner} from '../../_shared'; 3 | 4 | @Component({ 5 | selector: 'partner-details', 6 | templateUrl: './details.component.html', 7 | styleUrls: [ 8 | './details.component.scss' 9 | ], 10 | 11 | 12 | }) 13 | export class PartnerDetailsComponent implements OnInit { 14 | 15 | @Input() item: Partner; 16 | 17 | constructor() { 18 | } 19 | 20 | ngOnInit() { 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/app/library/partner/home.component.html: -------------------------------------------------------------------------------- 1 |
2 | 5 |
6 | 7 | -------------------------------------------------------------------------------- /src/app/library/partner/home.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/library/partner/home.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {ActivatedRoute} from '@angular/router'; 3 | import {PartnerApi, BasePageComponent, Partner, MenuItem} from '../../_shared'; 4 | import {Observable} from 'rxjs/Observable'; 5 | 6 | @Component({ 7 | selector: 'partner-home', 8 | templateUrl: './home.component.html', 9 | styleUrls: [ 10 | './home.component.scss' 11 | ], 12 | 13 | }) 14 | export class PartnerHomeComponent extends BasePageComponent { 15 | constructor(activatedRoute: ActivatedRoute, private api: PartnerApi) { 16 | super(activatedRoute); 17 | } 18 | 19 | items: Observable; 20 | 21 | reload(params): void { 22 | this.items = this.api.query() 23 | .map(partnerToMenuItem) 24 | .toArray(); 25 | } 26 | } 27 | 28 | function partnerToMenuItem(partner: Partner): MenuItem { 29 | return { 30 | title: partner.name, 31 | icon: partner.avatar, 32 | description: partner.description, 33 | url: `./${partner.id}` 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/app/library/partner/index.ts: -------------------------------------------------------------------------------- 1 | import {PartnerDetailsComponent} from './details.component'; 2 | import {PartnerListComponent} from './list.component'; 3 | import {PartnerHomeComponent} from './home.component'; 4 | import {PartnerShowComponent} from './show.component'; 5 | export * from './details.component'; 6 | export * from './home.component'; 7 | export * from './list.component'; 8 | export * from './show.component'; 9 | 10 | export const PARTNER_COMPONENTS = [PartnerDetailsComponent, PartnerListComponent, PartnerHomeComponent, PartnerShowComponent]; 11 | -------------------------------------------------------------------------------- /src/app/library/partner/list.component.html: -------------------------------------------------------------------------------- 1 |
2 | 指定的合作伙伴未找到 3 |
4 | 5 | -------------------------------------------------------------------------------- /src/app/library/partner/list.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/library/partner/list.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, Input} from '@angular/core'; 2 | import {MenuItem} from '../../_shared'; 3 | 4 | @Component({ 5 | selector: 'partner-list', 6 | templateUrl: './list.component.html', 7 | styleUrls: [ 8 | './list.component.scss' 9 | ], 10 | 11 | }) 12 | export class PartnerListComponent implements OnInit { 13 | constructor() { 14 | } 15 | 16 | @Input() items: MenuItem[]; 17 | 18 | ngOnInit() { 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/app/library/partner/show.component.html: -------------------------------------------------------------------------------- 1 |
2 | 8 |
9 | 10 | -------------------------------------------------------------------------------- /src/app/library/partner/show.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/library/partner/show.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {BasePageComponent, PartnerApi, Partner, matchById} from '../../_shared'; 3 | import {ActivatedRoute} from '@angular/router'; 4 | import {Observable} from 'rxjs/Observable'; 5 | 6 | @Component({ 7 | selector: 'partner-show', 8 | templateUrl: './show.component.html', 9 | styleUrls: [ 10 | './show.component.scss' 11 | ], 12 | 13 | }) 14 | export class PartnerShowComponent extends BasePageComponent { 15 | constructor(activatedRoute: ActivatedRoute, private api: PartnerApi) { 16 | super(activatedRoute); 17 | } 18 | 19 | item: Observable; 20 | 21 | reload(params: {id: string}): void { 22 | this.item = this.api.query() 23 | .find(matchById(params.id)) 24 | .do((item: Partner)=> { 25 | document.title = `${item.name} - Angular中文社区`; 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/app/library/resource/_README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/library/resource/_README.md -------------------------------------------------------------------------------- /src/app/library/resource/details.component.html: -------------------------------------------------------------------------------- 1 |

{{item.title}}

2 | 3 |

4 | {{author}} 5 | [译]{{translator}} 7 | 8 | 9 | 10 | 11 | 12 |

13 | 14 |

15 | {{item.originalUrl}} 16 |

17 | 18 |
19 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /src/app/library/resource/details.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/library/resource/details.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, Input} from '@angular/core'; 2 | import {Article} from '../../_shared'; 3 | 4 | @Component({ 5 | selector: 'resource-details', 6 | templateUrl: './details.component.html', 7 | styleUrls: [ 8 | './details.component.scss' 9 | ] 10 | }) 11 | export class ResourceDetailsComponent implements OnInit { 12 | 13 | @Input() item: Article; 14 | 15 | constructor() { 16 | } 17 | 18 | ngOnInit() { 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/app/library/resource/home.component.html: -------------------------------------------------------------------------------- 1 |
2 | 5 |
6 | 7 | -------------------------------------------------------------------------------- /src/app/library/resource/home.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/library/resource/home.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {ActivatedRoute} from '@angular/router'; 3 | import {ResourceApi, BasePageComponent, Article, MenuItem} from '../../_shared'; 4 | import {Observable} from 'rxjs/Observable'; 5 | 6 | @Component({ 7 | selector: 'resource-home', 8 | templateUrl: './home.component.html', 9 | styleUrls: [ 10 | './home.component.scss' 11 | ], 12 | 13 | }) 14 | export class ResourceHomeComponent extends BasePageComponent { 15 | constructor(activatedRoute: ActivatedRoute, private api: ResourceApi) { 16 | super(activatedRoute); 17 | } 18 | 19 | items: Observable; 20 | 21 | reload(params): void { 22 | this.items = this.api.query() 23 | .map(resourceToMenuItem) 24 | .toArray(); 25 | } 26 | } 27 | 28 | function resourceToMenuItem(resource: Article): MenuItem { 29 | return { 30 | title: resource.title, 31 | icon: resource.image, 32 | description: resource.summary, 33 | url: `/library/resource/${resource.id}` 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/app/library/resource/index.ts: -------------------------------------------------------------------------------- 1 | import {ResourceDetailsComponent} from './details.component'; 2 | import {ResourceListComponent} from './list.component'; 3 | import {ResourceHomeComponent} from './home.component'; 4 | import {ResourceShowComponent} from './show.component'; 5 | export * from './details.component'; 6 | export * from './home.component'; 7 | export * from './list.component'; 8 | export * from './show.component'; 9 | 10 | export const RESOURCE_COMPONENTS = [ResourceDetailsComponent, ResourceListComponent, ResourceHomeComponent, ResourceShowComponent]; 11 | -------------------------------------------------------------------------------- /src/app/library/resource/list.component.html: -------------------------------------------------------------------------------- 1 |
2 | 没有找到符合条件的新闻 3 |
4 | 5 | -------------------------------------------------------------------------------- /src/app/library/resource/list.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/library/resource/list.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, Input} from '@angular/core'; 2 | import {MenuItem} from '../../_shared'; 3 | 4 | @Component({ 5 | selector: 'resource-list', 6 | templateUrl: './list.component.html', 7 | styleUrls: [ 8 | './list.component.scss' 9 | ], 10 | 11 | }) 12 | export class ResourceListComponent implements OnInit { 13 | constructor() { 14 | } 15 | 16 | @Input() items: MenuItem[]; 17 | 18 | ngOnInit() { 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/app/library/resource/show.component.html: -------------------------------------------------------------------------------- 1 |
2 | 8 |
9 | 10 | -------------------------------------------------------------------------------- /src/app/library/resource/show.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/library/resource/show.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {BasePageComponent, ResourceApi, Article, matchById} from '../../_shared'; 3 | import {ActivatedRoute} from '@angular/router'; 4 | import {Observable} from 'rxjs/Observable'; 5 | 6 | @Component({ 7 | selector: 'resource-show', 8 | templateUrl: './show.component.html', 9 | styleUrls: [ 10 | './show.component.scss' 11 | ], 12 | 13 | }) 14 | export class ResourceShowComponent extends BasePageComponent { 15 | constructor(activatedRoute: ActivatedRoute, private api: ResourceApi) { 16 | super(activatedRoute); 17 | } 18 | 19 | item: Observable
; 20 | 21 | reload(params: {id: string}): void { 22 | this.item = this.api.query() 23 | .find(matchById(params.id)) 24 | .do((item: Article)=> { 25 | document.title = `${item.title} - Angular中文社区`; 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/app/not-found/index.ts: -------------------------------------------------------------------------------- 1 | export * from './not-found.component'; 2 | -------------------------------------------------------------------------------- /src/app/not-found/not-found.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'no-content', 5 | templateUrl: ` 6 |
7 |

404: page missing

8 |
9 | ` 10 | }) 11 | export class NotFoundComponent { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/app/user/_README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/app/user/_README.md -------------------------------------------------------------------------------- /src/app/user/_user-routing.module.ts: -------------------------------------------------------------------------------- 1 | import {RouterModule, Routes} from "@angular/router"; 2 | import {UserHomeComponent} from "./home.component"; 3 | import {UserLoginComponent} from "./login.component"; 4 | import {NgModule} from '@angular/core'; 5 | const routes: Routes = [ 6 | {path: '', data: {title: '个人中心'}, pathMatch: 'full', component: UserHomeComponent}, 7 | {path: 'login', data: {title: '登录'}, component: UserLoginComponent}, 8 | ]; 9 | 10 | @NgModule({ 11 | imports: [RouterModule.forChild(routes)], 12 | exports: [RouterModule] 13 | }) 14 | 15 | export class UserRoutingModule { 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/app/user/_user.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {CommonModule} from '@angular/common'; 3 | import { UserRoutingModule} from './_user-routing.module'; 4 | import {USER_COMPONENTS} from './index'; 5 | import SharedModule from '../_shared/_shared.module'; 6 | 7 | @NgModule({ 8 | imports: [ 9 | CommonModule, 10 | SharedModule, 11 | UserRoutingModule, 12 | ], 13 | declarations: [...USER_COMPONENTS], 14 | }) 15 | export default class UserModule { 16 | } 17 | -------------------------------------------------------------------------------- /src/app/user/home.component.html: -------------------------------------------------------------------------------- 1 | 您好!来自Github的 [ {{name}} ] 2 | -------------------------------------------------------------------------------- /src/app/user/home.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/user/home.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnDestroy, OnInit} from '@angular/core'; 2 | import {Router, ActivatedRoute} from '@angular/router'; 3 | import {Subscription} from 'rxjs/Subscription'; 4 | import {Auth} from '../_shared'; 5 | import {Http} from '@angular/http'; 6 | 7 | @Component({ 8 | selector: 'user-home', 9 | templateUrl: './home.component.html', 10 | styleUrls: [ 11 | './home.component.scss' 12 | ] 13 | }) 14 | export class UserHomeComponent implements OnInit, OnDestroy { 15 | constructor(private router: Router, private activatedRoute: ActivatedRoute, private auth: Auth, private http: Http) { 16 | } 17 | 18 | name: string; 19 | 20 | subscription: Subscription; 21 | 22 | ngOnInit() { 23 | this.subscription = this.activatedRoute.queryParams.subscribe((params: {code: string, state: string})=> { 24 | const state = params.state; 25 | const code = params.code; 26 | if (!state && !code) { 27 | return this.router.navigate(['/bbs']); 28 | } 29 | if (decodeURIComponent(state) !== this.auth.csrfToken) { 30 | alert('安全码不匹配,请联系管理员!'); 31 | } else { 32 | this.http.post('/api/github/user', { 33 | state: state, 34 | code: code, 35 | redirect_url: this.router.serializeUrl(this.router.createUrlTree(['/bbs/user/home'])) 36 | }).subscribe((data)=> { 37 | this.name = data.json().name; 38 | }, (err)=> { 39 | console.error(err); 40 | }); 41 | } 42 | }); 43 | } 44 | 45 | ngOnDestroy() { 46 | this.subscription.unsubscribe(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/app/user/index.ts: -------------------------------------------------------------------------------- 1 | import {UserHomeComponent} from './home.component'; 2 | import {UserLoginComponent} from './login.component'; 3 | export * from './home.component'; 4 | export * from './login.component'; 5 | export const USER_COMPONENTS = [UserHomeComponent, UserLoginComponent]; 6 | -------------------------------------------------------------------------------- /src/app/user/login.component.html: -------------------------------------------------------------------------------- 1 | 程序猿/媛?点此登录 3 | -------------------------------------------------------------------------------- /src/app/user/login.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/user/login.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {Auth} from '../_shared'; 3 | 4 | @Component({ 5 | selector: 'user-login', 6 | templateUrl: './login.component.html', 7 | styleUrls: [ 8 | './login.component.scss' 9 | ] 10 | }) 11 | export class UserLoginComponent implements OnInit { 12 | constructor(private auth: Auth) { 13 | } 14 | 15 | ngOnInit() { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-bbs/user-ui/4d028e852178740e77c01b70df6b5054e9140025/src/favicon.ico -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular中文社区 6 | 7 | 8 | 9 | 10 | 11 | 12 | 正在加载,请稍候... 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main.scss: -------------------------------------------------------------------------------- 1 | /* define application-wide styles and/or import third-party styles */ 2 | @import "./app/_shared/styles/bootstrap"; 3 | @import "./app/_shared/styles/material"; 4 | @import "./app/_shared/styles/bootstrap-extends"; 5 | @import "./app/_shared/styles/app"; 6 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | import { enableProdMode } from '@angular/core'; 3 | import { AppModule } from './app/app.module'; 4 | import { bootloader } from '@angularclass/hmr'; 5 | // import './vendor'; 6 | import './main.scss'; 7 | 8 | // if (environment.production) { 9 | // enableProdMode(); 10 | // } 11 | 12 | export function main(): Promise { 13 | return platformBrowserDynamic() 14 | .bootstrapModule(AppModule); 15 | } 16 | 17 | bootloader(main); 18 | 19 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | // Prefer CoreJS over the polyfills above 2 | import 'core-js/es6/symbol'; 3 | import 'core-js/es6/object'; 4 | import 'core-js/es6/function'; 5 | import 'core-js/es6/parse-int'; 6 | import 'core-js/es6/parse-float'; 7 | import 'core-js/es6/number'; 8 | import 'core-js/es6/math'; 9 | import 'core-js/es6/string'; 10 | import 'core-js/es6/date'; 11 | import 'core-js/es6/array'; 12 | import 'core-js/es6/regexp'; 13 | import 'core-js/es6/map'; 14 | import 'core-js/es6/set'; 15 | import 'core-js/es6/reflect'; 16 | import 'core-js/es7/reflect'; 17 | import 'zone.js/dist/zone'; 18 | -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | import 'core-js/es6'; 2 | import 'core-js/es7/reflect'; 3 | import 'ts-helpers'; 4 | import 'zone.js/dist/zone'; 5 | import 'zone.js/dist/long-stack-trace-zone'; 6 | import 'zone.js/dist/jasmine-patch'; 7 | import 'zone.js/dist/async-test'; 8 | import 'zone.js/dist/fake-async-test'; 9 | import 'zone.js/dist/sync-test'; 10 | 11 | // Typescript emit helpers polyfill 12 | 13 | // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. 14 | declare var __karma__: any; 15 | 16 | // Prevent Karma from running prematurely. 17 | __karma__.loaded = function () { 18 | }; 19 | 20 | 21 | Promise.all([ 22 | System.import('@angular/core/testing'), 23 | System.import('@angular/platform-browser-dynamic/testing') 24 | ]) 25 | // First, initialize the Angular testing environment. 26 | .then(([testing, testingBrowser]) => { 27 | testing.setBaseTestProviders( 28 | testingBrowser.TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS, 29 | testingBrowser.TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS 30 | ); 31 | }) 32 | // Then we find all the tests. 33 | .then(() => require.context('./', true, /\.spec\.ts/)) 34 | // And load the modules. 35 | .then(context => context.keys().map(context)) 36 | // Finally, start Karma to run the tests. 37 | .then(__karma__.start, __karma__.error); 38 | -------------------------------------------------------------------------------- /src/vendor.ts: -------------------------------------------------------------------------------- 1 | // Angular 2 2 | import '@angular/platform-browser'; 3 | import '@angular/platform-browser-dynamic'; 4 | import '@angular/core'; 5 | import '@angular/common'; 6 | import '@angular/forms'; 7 | import '@angular/http'; 8 | import '@angular/router'; 9 | 10 | // AngularClass 11 | import '@angularclass/hmr'; 12 | 13 | import 'rxjs/add/operator/map'; 14 | import 'rxjs/add/operator/switchMap'; 15 | import 'rxjs/add/operator/mergeMap'; 16 | import 'rxjs/add/operator/find'; 17 | import 'rxjs/add/operator/filter'; 18 | import 'rxjs/add/operator/first'; 19 | import 'rxjs/add/operator/do'; 20 | import 'rxjs/add/operator/toArray'; 21 | import 'rxjs/add/observable/from'; 22 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "allowSyntheticDefaultImports": true, 9 | "sourceMap": true, 10 | "strictNullChecks": false, 11 | "baseUrl": "./src", 12 | "paths": { 13 | }, 14 | "lib": [ 15 | "dom", 16 | "es6" 17 | ], 18 | "types": [ 19 | "hammerjs", 20 | "jasmine", 21 | "node", 22 | "protractor", 23 | "selenium-webdriver", 24 | "source-map", 25 | "uglify-js", 26 | "webpack" 27 | ] 28 | }, 29 | "exclude": [ 30 | "node_modules", 31 | "dist" 32 | ], 33 | "awesomeTypescriptLoaderOptions": { 34 | "forkChecker": true, 35 | "useWebpackText": true 36 | }, 37 | "compileOnSave": false, 38 | "buildOnSave": false, 39 | "atom": { "rewriteTsconfig": false } 40 | } 41 | -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "mode": "modules", 3 | "out": "doc", 4 | "theme": "default", 5 | "ignoreCompilerErrors": "true", 6 | "experimentalDecorators": "true", 7 | "emitDecoratorMetadata": "true", 8 | "target": "ES5", 9 | "moduleResolution": "node", 10 | "preserveConstEnums": "true", 11 | "stripInternal": "true", 12 | "suppressExcessPropertyErrors": "true", 13 | "suppressImplicitAnyIndexErrors": "true", 14 | "module": "commonjs" 15 | } 16 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: @AngularClass 3 | */ 4 | 5 | // Look in ./config folder for webpack.dev.js 6 | switch (process.env.NODE_ENV) { 7 | case 'prod': 8 | case 'production': 9 | module.exports = require('./config/webpack.prod')({env: 'production'}); 10 | break; 11 | case 'test': 12 | case 'testing': 13 | module.exports = require('./config/webpack.test')({env: 'test'}); 14 | break; 15 | case 'dev': 16 | case 'development': 17 | default: 18 | module.exports = require('./config/webpack.dev')({env: 'development'}); 19 | } 20 | --------------------------------------------------------------------------------