init 0428
This commit is contained in:
commit
b7111951df
13
.editorconfig
Normal file
13
.editorconfig
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Editor configuration, see https://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
46
.gitignore
vendored
Normal file
46
.gitignore
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# compiled output
|
||||
/dist
|
||||
/tmp
|
||||
/out-tsc
|
||||
# Only exists if Bazel was run
|
||||
/bazel-out
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# profiling files
|
||||
chrome-profiler-events*.json
|
||||
speed-measure-plugin*.json
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# IDE - VSCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
.history/*
|
||||
|
||||
# misc
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage
|
||||
/libpeerconnection.log
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
testem.log
|
||||
/typings
|
||||
|
||||
# System Files
|
||||
.DS_Store
|
||||
Thumbs.db
|
5
.prettierrc
Normal file
5
.prettierrc
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"trailingComma": "none",
|
||||
"tabWidth": 2,
|
||||
"singleQuote": true
|
||||
}
|
9
.storybook/main.js
Normal file
9
.storybook/main.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
module.exports = {
|
||||
stories: ['../src/**/*.stories.ts'],
|
||||
addons: [
|
||||
'@storybook/addon-actions',
|
||||
'@storybook/addon-links',
|
||||
'@storybook/addon-notes',
|
||||
'@storybook/addon-knobs'
|
||||
]
|
||||
};
|
9
.storybook/tsconfig.json
Normal file
9
.storybook/tsconfig.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"extends": "../tsconfig.app.json",
|
||||
"compilerOptions": {
|
||||
"types": ["node"]
|
||||
},
|
||||
"exclude": ["../src/test.ts", "../src/**/*.spec.ts"],
|
||||
"include": ["../src/**/*"],
|
||||
"files": ["./typings.d.ts"]
|
||||
}
|
4
.storybook/typings.d.ts
vendored
Normal file
4
.storybook/typings.d.ts
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
declare module '*.md' {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
11
.vscode/extensions.json
vendored
Normal file
11
.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"Angular.ng-template",
|
||||
"msjsdiag.debugger-for-chrome",
|
||||
"eamodio.gitlens",
|
||||
"esbenp.prettier-vscode",
|
||||
"ms-vscode.vscode-typescript-tslint-plugin",
|
||||
"VisualStudioExptTeam.vscodeintellicode",
|
||||
"nkokhelox.svg-font-previewer"
|
||||
]
|
||||
}
|
7
.vscode/launch.json
vendored
Normal file
7
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": []
|
||||
}
|
14
.vscode/settings.json
vendored
Normal file
14
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"editor.tabSize": 2,
|
||||
"editor.insertSpaces": true,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.autoClosingBrackets": "languageDefined",
|
||||
"editor.trimAutoWhitespace": true,
|
||||
"files.trimTrailingWhitespace": true,
|
||||
"files.trimFinalNewlines": true,
|
||||
"files.watcherExclude": {
|
||||
"**/dist": true
|
||||
},
|
||||
"debug.node.autoAttach": "off"
|
||||
}
|
15
.vscode/tasks.json
vendored
Normal file
15
.vscode/tasks.json
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "build:main:dev",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
27
README.md
Normal file
27
README.md
Normal file
|
@ -0,0 +1,27 @@
|
|||
# UcapLgMockup
|
||||
|
||||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 9.0.6.
|
||||
|
||||
## Development server
|
||||
|
||||
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
|
||||
|
||||
## Build
|
||||
|
||||
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||
|
||||
## Running end-to-end tests
|
||||
|
||||
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
|
||||
|
||||
## Further help
|
||||
|
||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
|
133
angular.json
Normal file
133
angular.json
Normal file
|
@ -0,0 +1,133 @@
|
|||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"ucap-lg-mockup": {
|
||||
"projectType": "application",
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
"style": "scss"
|
||||
}
|
||||
},
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"prefix": "app",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist/ucap-lg-mockup",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"aot": true,
|
||||
"assets": ["src/favicon.ico", "src/assets"],
|
||||
"styles": ["src/styles.scss"],
|
||||
"scripts": []
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"extractCss": true,
|
||||
"namedChunks": false,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": true,
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "5mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "6kb",
|
||||
"maximumError": "10kb"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hmr": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.hmr.ts"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"options": {
|
||||
"browserTarget": "ucap-lg-mockup:build",
|
||||
"hmrWarning": false
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "ucap-lg-mockup:build:production"
|
||||
},
|
||||
"hmr": {
|
||||
"hmr": true,
|
||||
"browserTarget": "ucap-lg-mockup:build:hmr"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "ucap-lg-mockup:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "src/test.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"karmaConfig": "karma.conf.js",
|
||||
"assets": ["src/favicon.ico", "src/assets"],
|
||||
"styles": ["src/styles.scss"],
|
||||
"scripts": []
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"tsconfig.app.json",
|
||||
"tsconfig.spec.json",
|
||||
"e2e/tsconfig.json"
|
||||
],
|
||||
"exclude": ["**/node_modules/**"]
|
||||
}
|
||||
},
|
||||
"e2e": {
|
||||
"builder": "@angular-devkit/build-angular:protractor",
|
||||
"options": {
|
||||
"protractorConfig": "e2e/protractor.conf.js",
|
||||
"devServerTarget": "ucap-lg-mockup:serve"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"devServerTarget": "ucap-lg-mockup:serve:production"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultProject": "ucap-lg-mockup",
|
||||
"cli": {
|
||||
"analytics": false
|
||||
}
|
||||
}
|
12
browserslist
Normal file
12
browserslist
Normal file
|
@ -0,0 +1,12 @@
|
|||
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
|
||||
# You can see what browsers were selected by your queries by running:
|
||||
# npx browserslist
|
||||
|
||||
> 0.5%
|
||||
last 2 versions
|
||||
Firefox ESR
|
||||
not dead
|
||||
not IE 9-11 # For IE 9-11 support, remove 'not'.
|
32
e2e/protractor.conf.js
Normal file
32
e2e/protractor.conf.js
Normal file
|
@ -0,0 +1,32 @@
|
|||
// @ts-check
|
||||
// Protractor configuration file, see link for more information
|
||||
// https://github.com/angular/protractor/blob/master/lib/config.ts
|
||||
|
||||
const { SpecReporter } = require('jasmine-spec-reporter');
|
||||
|
||||
/**
|
||||
* @type { import("protractor").Config }
|
||||
*/
|
||||
exports.config = {
|
||||
allScriptsTimeout: 11000,
|
||||
specs: [
|
||||
'./src/**/*.e2e-spec.ts'
|
||||
],
|
||||
capabilities: {
|
||||
browserName: 'chrome'
|
||||
},
|
||||
directConnect: true,
|
||||
baseUrl: 'http://localhost:4200/',
|
||||
framework: 'jasmine',
|
||||
jasmineNodeOpts: {
|
||||
showColors: true,
|
||||
defaultTimeoutInterval: 30000,
|
||||
print: function() {}
|
||||
},
|
||||
onPrepare() {
|
||||
require('ts-node').register({
|
||||
project: require('path').join(__dirname, './tsconfig.json')
|
||||
});
|
||||
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
|
||||
}
|
||||
};
|
23
e2e/src/app.e2e-spec.ts
Normal file
23
e2e/src/app.e2e-spec.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { AppPage } from './app.po';
|
||||
import { browser, logging } from 'protractor';
|
||||
|
||||
describe('workspace-project App', () => {
|
||||
let page: AppPage;
|
||||
|
||||
beforeEach(() => {
|
||||
page = new AppPage();
|
||||
});
|
||||
|
||||
it('should display welcome message', () => {
|
||||
page.navigateTo();
|
||||
expect(page.getTitleText()).toEqual('ucap-lg-mockup app is running!');
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
// Assert that there are no errors emitted from the browser
|
||||
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
|
||||
expect(logs).not.toContain(jasmine.objectContaining({
|
||||
level: logging.Level.SEVERE,
|
||||
} as logging.Entry));
|
||||
});
|
||||
});
|
11
e2e/src/app.po.ts
Normal file
11
e2e/src/app.po.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { browser, by, element } from 'protractor';
|
||||
|
||||
export class AppPage {
|
||||
navigateTo(): Promise<unknown> {
|
||||
return browser.get(browser.baseUrl) as Promise<unknown>;
|
||||
}
|
||||
|
||||
getTitleText(): Promise<string> {
|
||||
return element(by.css('app-root .content span')).getText() as Promise<string>;
|
||||
}
|
||||
}
|
13
e2e/tsconfig.json
Normal file
13
e2e/tsconfig.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../out-tsc/e2e",
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"types": [
|
||||
"jasmine",
|
||||
"jasminewd2",
|
||||
"node"
|
||||
]
|
||||
}
|
||||
}
|
32
karma.conf.js
Normal file
32
karma.conf.js
Normal file
|
@ -0,0 +1,32 @@
|
|||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage-istanbul-reporter'),
|
||||
require('@angular-devkit/build-angular/plugins/karma')
|
||||
],
|
||||
client: {
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
coverageIstanbulReporter: {
|
||||
dir: require('path').join(__dirname, './coverage/ucap-lg-mockup'),
|
||||
reports: ['html', 'lcovonly', 'text-summary'],
|
||||
fixWebpackSourcePaths: true
|
||||
},
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['Chrome'],
|
||||
singleRun: false,
|
||||
restartOnFileChange: true
|
||||
});
|
||||
};
|
18664
package-lock.json
generated
Normal file
18664
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
64
package.json
Normal file
64
package.json
Normal file
|
@ -0,0 +1,64 @@
|
|||
{
|
||||
"name": "ucap-lg-mockup",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"start:hmr": "ng serve --configuration hmr",
|
||||
"build": "ng build",
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e",
|
||||
"storybook": "start-storybook -p 6006",
|
||||
"build-storybook": "build-storybook"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "~9.0.6",
|
||||
"@angular/cdk": "^9.2.1",
|
||||
"@angular/common": "~9.0.6",
|
||||
"@angular/compiler": "~9.0.6",
|
||||
"@angular/core": "~9.0.6",
|
||||
"@angular/flex-layout": "^9.0.0-beta.29",
|
||||
"@angular/forms": "~9.0.6",
|
||||
"@angular/material": "^9.2.1",
|
||||
"@angular/material-moment-adapter": "^9.2.1",
|
||||
"@angular/platform-browser": "~9.0.6",
|
||||
"@angular/platform-browser-dynamic": "~9.0.6",
|
||||
"@angular/router": "~9.0.6",
|
||||
"ngx-perfect-scrollbar": "^9.0.0",
|
||||
"rxjs": "~6.5.4",
|
||||
"tslib": "^1.10.0",
|
||||
"zone.js": "~0.10.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "~0.900.6",
|
||||
"@angular/cli": "~9.0.6",
|
||||
"@angular/compiler-cli": "~9.0.6",
|
||||
"@angular/language-service": "~9.0.6",
|
||||
"@angularclass/hmr": "^2.1.3",
|
||||
"@babel/core": "^7.9.0",
|
||||
"@storybook/addon-actions": "^5.3.18",
|
||||
"@storybook/addon-links": "^5.3.18",
|
||||
"@storybook/addon-notes": "^5.3.18",
|
||||
"@storybook/addon-knobs": "5.3.18",
|
||||
"@storybook/addons": "^5.3.18",
|
||||
"@storybook/angular": "^5.3.18",
|
||||
"@types/jasmine": "~3.5.0",
|
||||
"@types/jasminewd2": "~2.0.3",
|
||||
"@types/node": "^12.11.1",
|
||||
"babel-loader": "^8.1.0",
|
||||
"codelyzer": "^5.1.2",
|
||||
"jasmine-core": "~3.5.0",
|
||||
"jasmine-spec-reporter": "~4.2.1",
|
||||
"karma": "~4.3.0",
|
||||
"karma-chrome-launcher": "~3.1.0",
|
||||
"karma-coverage-istanbul-reporter": "~2.1.0",
|
||||
"karma-jasmine": "~2.0.1",
|
||||
"karma-jasmine-html-reporter": "^1.4.2",
|
||||
"protractor": "~5.4.3",
|
||||
"ts-node": "~8.3.0",
|
||||
"tslint": "~5.18.0",
|
||||
"typescript": "~3.7.5"
|
||||
}
|
||||
}
|
27
src/app/app-routing.module.ts
Normal file
27
src/app/app-routing.module.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
import { LoginComponent } from './pages/account/login.component';
|
||||
import { GroupComponent } from './pages/group/group.component';
|
||||
import { ChatComponent } from './pages/chat/chat.component';
|
||||
import { OrganizationComponent } from './pages/organization/organization.component';
|
||||
import { MessageComponent } from './pages/message/message.component';
|
||||
import { CallComponent } from './pages/call/call.component';
|
||||
import { CommonComponent } from './pages/common/common.component';
|
||||
import { LoadingComponent } from './pages/common/loading.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: 'login', component: LoginComponent },
|
||||
{ path: 'group', component: GroupComponent },
|
||||
{ path: 'chat', component: ChatComponent },
|
||||
{ path: 'organization', component: OrganizationComponent },
|
||||
{ path: 'message', component: MessageComponent },
|
||||
{ path: 'call', component: CallComponent },
|
||||
{ path: 'common', component: CommonComponent },
|
||||
{ path: 'loading', component: LoadingComponent }
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule {}
|
1
src/app/app.component.html
Normal file
1
src/app/app.component.html
Normal file
|
@ -0,0 +1 @@
|
|||
<router-outlet></router-outlet>
|
0
src/app/app.component.scss
Normal file
0
src/app/app.component.scss
Normal file
35
src/app/app.component.spec.ts
Normal file
35
src/app/app.component.spec.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import { TestBed, async } from '@angular/core/testing';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
RouterTestingModule
|
||||
],
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
it('should create the app', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
});
|
||||
|
||||
it(`should have as title 'ucap-lg-mockup'`, () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app.title).toEqual('ucap-lg-mockup');
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement;
|
||||
expect(compiled.querySelector('.content span').textContent).toContain('ucap-lg-mockup app is running!');
|
||||
});
|
||||
});
|
10
src/app/app.component.ts
Normal file
10
src/app/app.component.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.scss']
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'ucap-lg-mockup';
|
||||
}
|
59
src/app/app.module.ts
Normal file
59
src/app/app.module.ts
Normal file
|
@ -0,0 +1,59 @@
|
|||
import { CommonModule } from '@angular/common';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { ScrollingModule } from '@angular/cdk/scrolling';
|
||||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { MaterialModule } from './material.module';
|
||||
import { LoginComponent } from './pages/account/login.component';
|
||||
import { GroupComponent } from './pages/group/group.component';
|
||||
import { OrganizationComponent } from './pages/organization/organization.component';
|
||||
import { ChatComponent } from './pages/chat/chat.component';
|
||||
import { MessageComponent } from './pages/message/message.component';
|
||||
import { CommonComponent } from './pages/common/common.component';
|
||||
import { LoadingComponent } from './pages/common/loading.component';
|
||||
import { CallComponent } from './pages/call/call.component';
|
||||
import { UserItemComponent } from './pages/group/component/user-item.component';
|
||||
import { TreeComponent } from './pages/organization/component/tree.component';
|
||||
import { DetailTableComponent } from './pages/organization/component/detail-table.component';
|
||||
import { ChatItemComponent } from './pages/chat/component/chat-item.component';
|
||||
import { NewGroupComponent } from './pages/common/popup/new-group.component';
|
||||
import { NewChatComponent } from './pages/common/popup/new-chat.component';
|
||||
import { SettingComponent } from './pages/common/popup/setting.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
|
||||
LoginComponent,
|
||||
GroupComponent,
|
||||
OrganizationComponent,
|
||||
ChatComponent,
|
||||
MessageComponent,
|
||||
CommonComponent,
|
||||
CallComponent,
|
||||
LoadingComponent,
|
||||
UserItemComponent,
|
||||
TreeComponent,
|
||||
DetailTableComponent,
|
||||
ChatItemComponent,
|
||||
NewGroupComponent,
|
||||
NewChatComponent,
|
||||
SettingComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
BrowserModule,
|
||||
BrowserAnimationsModule,
|
||||
ReactiveFormsModule,
|
||||
AppRoutingModule,
|
||||
ScrollingModule,
|
||||
MaterialModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule {}
|
47
src/app/app.theme.scss
Normal file
47
src/app/app.theme.scss
Normal file
|
@ -0,0 +1,47 @@
|
|||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Typography
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
// Angular Material typography
|
||||
// $input: mat-typography-level(16px, 1.125, 400) // line-height must be unitless !!!
|
||||
$typography: mat-typography-config(
|
||||
$font-family:
|
||||
'나눔고딕, Malgun Gothic, 맑은고딕, Arial, Muli, Helvetica Neue, Arial, sans-serif',
|
||||
$title: mat-typography-level(20px, 32px, 600),
|
||||
$body-2: mat-typography-level(14px, 24px, 600),
|
||||
$button: mat-typography-level(14px, 14px, 600),
|
||||
$input: mat-typography-level(16px, 1.125, 400)
|
||||
);
|
||||
|
||||
// Setup the typography
|
||||
@include angular-material-typography($typography);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Define theme --LG RED
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// Define the palettes for your theme using the Material Design palettes available in palette.scss
|
||||
// (imported above). For each palette, you can optionally specify a default, lighter, and darker
|
||||
// hue. Available color palettes: https://material.io/design/color/
|
||||
$lgRed-app-primary: mat-palette($lg-red);
|
||||
$lgRed-app-accent: mat-palette($lg-red, A200, A100, A400);
|
||||
|
||||
// The warn palette is optional (defaults to red).
|
||||
$lgRed-app-warn: mat-palette($lg-red);
|
||||
|
||||
// Create the theme object (a Sass map containing all of the palettes).
|
||||
$lgRed-app-theme: mat-light-theme(
|
||||
$lgRed-app-primary,
|
||||
$lgRed-app-accent,
|
||||
$lgRed-app-warn
|
||||
);
|
||||
|
||||
// Include theme styles for core and each component used in your app.
|
||||
// Alternatively, you can import and @include the theme mixins for each component
|
||||
// that you are using.
|
||||
@include angular-material-theme($lgRed-app-theme);
|
||||
|
||||
// Apply the theme to the user components
|
||||
/*
|
||||
@include components-theme($lgRed-app-theme);
|
||||
*/
|
||||
@include ucap-material-theme($lgRed-app-theme);
|
76
src/app/material.module.ts
Normal file
76
src/app/material.module.ts
Normal file
|
@ -0,0 +1,76 @@
|
|||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatButtonToggleModule } from '@angular/material/button-toggle';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatChipsModule } from '@angular/material/chips';
|
||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { MatGridListModule } from '@angular/material/grid-list';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatListModule } from '@angular/material/list';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatRadioModule } from '@angular/material/radio';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatSidenavModule } from '@angular/material/sidenav';
|
||||
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||
import { MatSliderModule } from '@angular/material/slider';
|
||||
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||
import { MatStepperModule } from '@angular/material/stepper';
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { MatPaginatorModule } from '@angular/material/paginator';
|
||||
import { MatSortModule } from '@angular/material/sort';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { MatTreeModule } from '@angular/material/tree';
|
||||
import { MatBadgeModule } from '@angular/material/badge';
|
||||
|
||||
const MODULE = [
|
||||
MatAutocompleteModule,
|
||||
MatButtonModule,
|
||||
MatButtonToggleModule,
|
||||
MatBadgeModule,
|
||||
MatCardModule,
|
||||
MatChipsModule,
|
||||
MatDatepickerModule,
|
||||
MatDialogModule,
|
||||
MatExpansionModule,
|
||||
MatGridListModule,
|
||||
MatIconModule,
|
||||
MatInputModule,
|
||||
MatListModule,
|
||||
MatMenuModule,
|
||||
MatProgressBarModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatRadioModule,
|
||||
MatCheckboxModule,
|
||||
MatSelectModule,
|
||||
MatSidenavModule,
|
||||
MatSlideToggleModule,
|
||||
MatSliderModule,
|
||||
MatSnackBarModule,
|
||||
MatStepperModule,
|
||||
MatTabsModule,
|
||||
MatTooltipModule,
|
||||
MatPaginatorModule,
|
||||
MatSortModule,
|
||||
MatToolbarModule,
|
||||
MatTableModule,
|
||||
MatFormFieldModule,
|
||||
MatTreeModule
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [...MODULE],
|
||||
exports: [...MODULE]
|
||||
})
|
||||
export class MaterialModule {}
|
65
src/app/pages/account/login.component.html
Normal file
65
src/app/pages/account/login.component.html
Normal file
|
@ -0,0 +1,65 @@
|
|||
<div class="login-container">
|
||||
<div class="login-box">
|
||||
<div class="logo-img">
|
||||
<img src="../../../assets/images/logo_140.png" alt="" />
|
||||
</div>
|
||||
<h1>Welcome to Messenger</h1>
|
||||
<div class="login-content">
|
||||
<mat-form-field class="example-full-width" appearance="none">
|
||||
<mat-select
|
||||
(change)="onChange($event)"
|
||||
placeholder="선택"
|
||||
class="login-input-area login-select-form"
|
||||
>
|
||||
<mat-option *ngFor="let company of companyList" [value]="company">
|
||||
{{ company.companyName }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<div class="login-input-area idpass-type">
|
||||
<mat-form-field
|
||||
class="login-idpass-txt"
|
||||
appearance="none"
|
||||
floatLabel=""
|
||||
>
|
||||
<mat-label>ID</mat-label>
|
||||
<input matInput placeholder="ID" value="" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="login-input-area idpass-type pass-type">
|
||||
<mat-form-field class="login-idpass-txt" appearance="none">
|
||||
<mat-label>Password</mat-label>
|
||||
<input matInput type="password" placeholder="Password" value="" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="error-container">
|
||||
<mat-error *ngIf="isLoginId">
|
||||
아이디를 입력하세요.
|
||||
</mat-error>
|
||||
<mat-error *ngIf="isLoginId">
|
||||
패스워드 입력하세요.
|
||||
</mat-error>
|
||||
</div>
|
||||
<button mat-raised-button class="login-input-submit" aria-label="LOG IN">
|
||||
로그인
|
||||
</button>
|
||||
|
||||
<div class="login-chk-area">
|
||||
<mat-checkbox>Remember Me</mat-checkbox>
|
||||
<mat-checkbox>실행 시 자동 로그인</mat-checkbox>
|
||||
</div>
|
||||
<div class="login-pass-info">
|
||||
<ul>
|
||||
<li><a href="">비밀번호 찾기</a></li>
|
||||
<li><a href="" class="fir-pass">비밀번호 초기화</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="login-button-area">
|
||||
<button type="button">이용 시 주의 사항</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
330
src/app/pages/account/login.component.scss
Normal file
330
src/app/pages/account/login.component.scss
Normal file
|
@ -0,0 +1,330 @@
|
|||
@charset 'UTF-8';
|
||||
|
||||
@import '../../../assets/scss/components';
|
||||
|
||||
$login-bg-w: 100/1920;
|
||||
$login-bg-h: 100/1080;
|
||||
|
||||
.login-container {
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
background-color: $bg-gray;
|
||||
background-image: url(../../../assets/images/bg/bg_login_circle_square01.svg),
|
||||
url(../../../assets/images/bg/bg_login_circle_stroke01.svg),
|
||||
url(../../../assets/images/bg/bg_login_circle01.svg),
|
||||
url(../../../assets/images/bg/bg_login_circle03.svg),
|
||||
url(../../../assets/images/bg/bg_login_circle_diagonal01.svg),
|
||||
url(../../../assets/images/bg/bg_login_circle_square02.svg),
|
||||
url(../../../assets/images/bg/bg_login_circle04.svg),
|
||||
url(../../../assets/images/bg/bg_login_circle05.svg),
|
||||
url(../../../assets/images/bg/bg_login_circle06.svg),
|
||||
url(../../../assets/images/bg/bg_login_circle07.svg),
|
||||
url(../../../assets/images/bg/bg_login_circle08.svg),
|
||||
url(../../../assets/images/bg/bg_login_circle_diagonal02.svg),
|
||||
url(../../../assets/images/bg/bg_login_circle_diagonal03.svg),
|
||||
url(../../../assets/images/bg/bg_login_circle_stroke02.svg),
|
||||
url(../../../assets/images/bg/bg_login_circle_stroke03.svg),
|
||||
url(../../../assets/images/bg/bg_login_circle_stroke04.svg),
|
||||
url(../../../assets/images/bg/bg_login_circle_stroke05.svg),
|
||||
url(../../../assets/images/bg/bg_login_polygon01.svg),
|
||||
url(../../../assets/images/bg/bg_login_polygon02.svg);
|
||||
background-repeat: no-repeat;
|
||||
background-position: unquote($login-bg-w * 323 + '%')
|
||||
unquote($login-bg-h * 179 + '%'),
|
||||
unquote($login-bg-w * -147 + '%') unquote($login-bg-h * 18 + '%'),
|
||||
unquote($login-bg-w * 285 + '%') unquote($login-bg-h * 226 + '%'),
|
||||
unquote($login-bg-w * 1235 + '%') unquote($login-bg-h * -101 + '%'),
|
||||
unquote($login-bg-w * 1397 + '%') unquote($login-bg-h * 163 + '%'),
|
||||
unquote($login-bg-w * 1569 + '%') unquote($login-bg-h * 580 + '%'),
|
||||
unquote($login-bg-w * 426 + '%') unquote($login-bg-h * 293 + '%'),
|
||||
unquote($login-bg-w * 1531 + '%') unquote($login-bg-h * 250 + '%'),
|
||||
unquote($login-bg-w * 1774 + '%') unquote($login-bg-h * 166 + '%'),
|
||||
unquote($login-bg-w * 1362 + '%') unquote($login-bg-h * 673 + '%'),
|
||||
unquote($login-bg-w * 152 + '%') unquote($login-bg-h * 730 + '%'),
|
||||
unquote($login-bg-w * 286 + '%') unquote($login-bg-h * 719 + '%'),
|
||||
unquote($login-bg-w * 683 + '%') unquote($login-bg-h * 593 + '%'),
|
||||
unquote($login-bg-w * 498 + '%') unquote($login-bg-h * 453 + '%'),
|
||||
unquote($login-bg-w * 1709 + '%') unquote($login-bg-h * 599 + '%'),
|
||||
unquote($login-bg-w * 1395 + '%') unquote($login-bg-h * 989 + '%'),
|
||||
unquote(100 + $login-bg-w * 89 + '%') unquote(100 + $login-bg-h * 137 + '%'),
|
||||
unquote($login-bg-w * 90 + '%') unquote($login-bg-h * 463 + '%'),
|
||||
unquote($login-bg-w * 549 + '%') unquote($login-bg-h * 874 + '%');
|
||||
background-size: unquote($login-bg-w * 79 + '%'),
|
||||
unquote($login-bg-w * 333 + '%'), unquote($login-bg-w * 84 + '%'),
|
||||
unquote($login-bg-w * 172 + '%'), unquote($login-bg-w * 210 + '%'),
|
||||
unquote($login-bg-w * 94 + '%'), unquote($login-bg-w * 44 + '%'),
|
||||
unquote($login-bg-w * 118 + '%'), unquote($login-bg-w * 52 + '%'),
|
||||
unquote($login-bg-w * 70 + '%'), unquote($login-bg-w * 172 + '%'),
|
||||
unquote($login-bg-w * 82 + '%'), unquote($login-bg-w * 135 + '%'),
|
||||
unquote($login-bg-w * 102 + '%'), unquote($login-bg-w * 130 + '%'),
|
||||
unquote($login-bg-w * 184 + '%'), unquote($login-bg-w * 370 + '%'),
|
||||
unquote($login-bg-w * 122 + '%'), unquote($login-bg-w * 75 + '%');
|
||||
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.login-box {
|
||||
@extend %clearfix;
|
||||
padding: 0 0 45px;
|
||||
width: 420px;
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
flex-basis: auto;
|
||||
align-items: center;
|
||||
.logo-img {
|
||||
display: block;
|
||||
text-align: center;
|
||||
img {
|
||||
margin-bottom: 7px;
|
||||
vertical-align: top;
|
||||
@include screen(mid) {
|
||||
width: 120px;
|
||||
}
|
||||
@include screen(xs) {
|
||||
width: 100px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@extend %guideline; //Guide Line
|
||||
h1 {
|
||||
@include font-family($font-light);
|
||||
font-size: 24px;
|
||||
text-align: center;
|
||||
color: $txt-color01;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
@include screen(mid) {
|
||||
font-size: 19px;
|
||||
}
|
||||
@include screen(xs) {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
.login-content {
|
||||
@extend %guideline2; //Guide Line2
|
||||
margin: 30px auto 0;
|
||||
.login-input-area {
|
||||
border: 1px solid #cccccc;
|
||||
border-radius: 2px;
|
||||
width: 100%;
|
||||
max-width: 420px;
|
||||
min-width: 150px;
|
||||
height: 60px;
|
||||
background-color: $white;
|
||||
margin-top: 10px;
|
||||
&.login-select-form {
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
padding: 0 16px;
|
||||
@include screen(mid) {
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
}
|
||||
@include screen(xs) {
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
}
|
||||
}
|
||||
&:first-of-type {
|
||||
margin-top: 0px;
|
||||
}
|
||||
&.idpass-type {
|
||||
padding-left: 50px;
|
||||
position: relative;
|
||||
&::before {
|
||||
font-family: 'material Icons';
|
||||
font-size: 24px;
|
||||
text-align: center;
|
||||
line-height: 60px;
|
||||
content: 'perm_identity';
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 16px;
|
||||
@include screen(mid) {
|
||||
line-height: 50px;
|
||||
}
|
||||
@include screen(xs) {
|
||||
line-height: 42px;
|
||||
}
|
||||
}
|
||||
&.pass-type {
|
||||
&::before {
|
||||
content: 'https';
|
||||
}
|
||||
}
|
||||
.login-idpass-txt {
|
||||
width: 368px;
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
font-size: 14px;
|
||||
@include screen(mid) {
|
||||
width: 358 - 60 + px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
font-size: 14px;
|
||||
}
|
||||
@include screen(xs) {
|
||||
width: 308 - 60 + px;
|
||||
font-size: 14px;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
}
|
||||
input {
|
||||
font-size: 18px;
|
||||
line-height: 58px;
|
||||
margin-top: 0;
|
||||
vertical-align: top;
|
||||
background-color: $white;
|
||||
padding: 0 10px 0 5px;
|
||||
@include screen(mid) {
|
||||
font-size: 16px;
|
||||
line-height: 48px;
|
||||
}
|
||||
@include screen(xs) {
|
||||
font-size: 14px;
|
||||
line-height: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@include screen(mid) {
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
.login-input-submit {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
background-color: $black;
|
||||
border-radius: 2px;
|
||||
color: $white;
|
||||
font-size: 20px;
|
||||
@include font-family($font-semibold);
|
||||
border: 0;
|
||||
margin-top: 12px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
@include screen(mid) {
|
||||
margin-top: 8px;
|
||||
font-size: 16px;
|
||||
height: 50px;
|
||||
}
|
||||
@include screen(xs) {
|
||||
font-size: 14px;
|
||||
height: 42px;
|
||||
}
|
||||
}
|
||||
@include screen(mid) {
|
||||
margin-top: 23px;
|
||||
width: 350px;
|
||||
.login-input-area {
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
@include screen(xs) {
|
||||
margin-top: 23px;
|
||||
width: 300px;
|
||||
.login-input-area {
|
||||
height: 42px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.login-chk-area {
|
||||
margin-top: 6px;
|
||||
font-size: 13px;
|
||||
text-align: left;
|
||||
@include screen(xs) {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
.login-pass-info {
|
||||
overflow: hidden;
|
||||
margin-top: 83px;
|
||||
ul {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
li {
|
||||
height: 24px;
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0 12% 0 8%;
|
||||
&::before {
|
||||
content: '';
|
||||
height: 11px;
|
||||
width: 1px;
|
||||
display: flex;
|
||||
background-color: $gray-re4a;
|
||||
position: absolute;
|
||||
top: 6.5px;
|
||||
left: 0;
|
||||
}
|
||||
&:first-child {
|
||||
padding-left: 0;
|
||||
&::before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
&:last-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
a {
|
||||
line-height: 24px;
|
||||
font-size: 12px;
|
||||
color: $gray-re4a;
|
||||
padding-left: 34px;
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
&::before {
|
||||
font-family: 'material Icons';
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
content: 'search';
|
||||
color: $white;
|
||||
display: block;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
background-color: $black;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
&.fir-pass {
|
||||
&::before {
|
||||
content: 'sync';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.login-button-area {
|
||||
margin-top: 14px;
|
||||
@include screen(xs) {
|
||||
margin-top: 20px;
|
||||
}
|
||||
button {
|
||||
border: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 46px;
|
||||
border-radius: 4px;
|
||||
background-color: #e0e3e7;
|
||||
font-size: 12px;
|
||||
color: $gray-re4a;
|
||||
cursor: pointer;
|
||||
@include screen(mid) {
|
||||
height: 38px;
|
||||
}
|
||||
@include screen(xs) {
|
||||
height: 34px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.example-full-width {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
46
src/app/pages/account/login.component.stories.ts
Normal file
46
src/app/pages/account/login.component.stories.ts
Normal file
|
@ -0,0 +1,46 @@
|
|||
import { action } from '@storybook/addon-actions';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { array, boolean, text, object } from '@storybook/addon-knobs/angular';
|
||||
|
||||
import { LoginComponent } from './login.component';
|
||||
import { moduleMetadata } from '@storybook/angular';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
|
||||
export default {
|
||||
title: 'LoginComponent',
|
||||
component: LoginComponent,
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
imports: [BrowserModule, BrowserAnimationsModule, MaterialModule],
|
||||
providers: []
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
const defaultProbs = (overrides = {}) =>
|
||||
Object.assign(
|
||||
{},
|
||||
{
|
||||
companyList: array('companyList', [
|
||||
{ companyName: 'LG CNS' },
|
||||
{ companyName: 'LG UCAP' }
|
||||
]),
|
||||
isLoginId: false,
|
||||
isPasswd: false,
|
||||
placeholder: text('placeholder', '선택'),
|
||||
disabled: boolean('disabled', false),
|
||||
onChange: action('change')
|
||||
},
|
||||
overrides
|
||||
);
|
||||
|
||||
export const Page = () => ({
|
||||
component: LoginComponent,
|
||||
props: defaultProbs()
|
||||
});
|
||||
|
||||
export const ErrorPage = () => ({
|
||||
component: LoginComponent,
|
||||
props: defaultProbs({ isLoginId: true, isPasswd: true })
|
||||
});
|
18
src/app/pages/account/login.component.ts
Normal file
18
src/app/pages/account/login.component.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { Component, OnInit, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-pages-account-login',
|
||||
templateUrl: './login.component.html',
|
||||
styleUrls: ['./login.component.scss']
|
||||
})
|
||||
export class LoginComponent implements OnInit {
|
||||
constructor() {}
|
||||
|
||||
companyList;
|
||||
selected;
|
||||
isLoginId;
|
||||
isPasswd;
|
||||
ngOnInit(): void {}
|
||||
|
||||
onChange(event: MouseEvent) {}
|
||||
}
|
1
src/app/pages/call/call.component.html
Normal file
1
src/app/pages/call/call.component.html
Normal file
|
@ -0,0 +1 @@
|
|||
<p>call works!</p>
|
0
src/app/pages/call/call.component.scss
Normal file
0
src/app/pages/call/call.component.scss
Normal file
25
src/app/pages/call/call.component.spec.ts
Normal file
25
src/app/pages/call/call.component.spec.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CallComponent } from './call.component';
|
||||
|
||||
describe('CallComponent', () => {
|
||||
let component: CallComponent;
|
||||
let fixture: ComponentFixture<CallComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ CallComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CallComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
22
src/app/pages/call/call.component.stories.ts
Normal file
22
src/app/pages/call/call.component.stories.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { action } from '@storybook/addon-actions';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
import { moduleMetadata } from '@storybook/angular';
|
||||
import { CallComponent } from './call.component';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
|
||||
export default {
|
||||
title: 'CallComponent',
|
||||
component: CallComponent,
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
imports: [BrowserModule, BrowserAnimationsModule, MaterialModule],
|
||||
providers: []
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
export const Page = () => ({
|
||||
component: CallComponent
|
||||
});
|
15
src/app/pages/call/call.component.ts
Normal file
15
src/app/pages/call/call.component.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-call',
|
||||
templateUrl: './call.component.html',
|
||||
styleUrls: ['./call.component.scss']
|
||||
})
|
||||
export class CallComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
}
|
529
src/app/pages/chat/chat.component.html
Normal file
529
src/app/pages/chat/chat.component.html
Normal file
|
@ -0,0 +1,529 @@
|
|||
<div class="container">
|
||||
<div class="gnb">
|
||||
<mat-toolbar>logo</mat-toolbar>
|
||||
<mat-tab-group
|
||||
mat-stretch-tabs
|
||||
animationDuration="0ms"
|
||||
backgroundColor="transparent"
|
||||
class="global-menu"
|
||||
>
|
||||
<mat-tab aria-label="Group">
|
||||
<ng-template mat-tab-label>
|
||||
<div class="icon-item" matTooltip="그룹" matTooltipPosition="after">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
|
||||
<circle cx="12" cy="7" r="4"></circle>
|
||||
</svg>
|
||||
</div>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
<mat-tab aria-label="Chat">
|
||||
<ng-template mat-tab-label>
|
||||
<div
|
||||
class="icon-item"
|
||||
matBadgeHidden="false"
|
||||
matBadge="275"
|
||||
matBadgeColor="accent"
|
||||
matBadgePosition="above after"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="#000000"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="bevel"
|
||||
>
|
||||
<path
|
||||
d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
<mat-tab aria-label="Organization">
|
||||
<ng-template mat-tab-label>
|
||||
<div class="icon-item">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="#000000"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="bevel"
|
||||
>
|
||||
<circle class="st0" cx="18.4" cy="18.5" r="3" />
|
||||
<circle class="st0" cx="12" cy="5" r="3" />
|
||||
<path class="st0" d="M12.4,10.5h4c1.1,0,2,0.9,2,2v3" />
|
||||
<circle class="st0" cx="6.1" cy="18.5" r="3" />
|
||||
<path class="st0" d="M6.1,15.5v-3c0-1.1,0.9-2,2-2h4" />
|
||||
<line class="st0" x1="12" y1="8" x2="12" y2="9" />
|
||||
</svg>
|
||||
</div>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
|
||||
<mat-tab aria-label="Message">
|
||||
<ng-template mat-tab-label>
|
||||
<div class="icon-item">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="#000000"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="bevel"
|
||||
>
|
||||
<polygon
|
||||
points="21.368 12.001 3 21.609 3 14 11 12 3 9.794 3 2.394"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</div>
|
||||
|
||||
<div class="menu-container">
|
||||
<div class="contents">
|
||||
<mat-drawer-container class="example-container" style="height: 600px;">
|
||||
<mat-drawer #drawer mode="side" opened style="width: 400px;">
|
||||
<mat-toolbar>
|
||||
<div>M Messenger</div>
|
||||
<div></div>
|
||||
</mat-toolbar>
|
||||
<div class="list-section">
|
||||
<div class="title-section">
|
||||
<div class="title">
|
||||
<h3>대화</h3>
|
||||
<div class="btn-box">
|
||||
<button
|
||||
mat-icon-button
|
||||
[matMenuTriggerFor]="menu"
|
||||
aria-label="group menu"
|
||||
>
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="search-area">
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label>대화방명, 대화 참여자 검색</mat-label>
|
||||
<input
|
||||
matInput
|
||||
placeholder="대화방명, 대화 참여자 검색"
|
||||
value=""
|
||||
/>
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list">
|
||||
<mat-accordion>
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
2020년 04월 05일 목요일 (<span>오늘</span>)
|
||||
<button
|
||||
mat-icon-button
|
||||
[matMenuTriggerFor]="menu"
|
||||
aria-label="group menu"
|
||||
>
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
</mat-panel-title>
|
||||
<mat-panel-description></mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
<app-chat-item></app-chat-item>
|
||||
<app-chat-item></app-chat-item>
|
||||
<app-chat-item></app-chat-item>
|
||||
<app-chat-item></app-chat-item>
|
||||
<app-chat-item></app-chat-item>
|
||||
</mat-expansion-panel>
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
2020년 04월 04일 수요일
|
||||
<button
|
||||
mat-icon-button
|
||||
[matMenuTriggerFor]="menu"
|
||||
aria-label="group menu"
|
||||
>
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
</mat-panel-title>
|
||||
<mat-panel-description></mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
<app-chat-item></app-chat-item>
|
||||
<app-chat-item></app-chat-item>
|
||||
<app-chat-item></app-chat-item>
|
||||
<app-chat-item></app-chat-item>
|
||||
<app-chat-item></app-chat-item>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
</div>
|
||||
</div>
|
||||
</mat-drawer>
|
||||
<mat-drawer-content style="width: 900px;">
|
||||
<button
|
||||
mat-icon-button
|
||||
class="left-drawer-toggle"
|
||||
(click)="drawer.toggle()"
|
||||
>
|
||||
<
|
||||
</button>
|
||||
<mat-toolbar>
|
||||
<div><span>Today</span>2020.05.05</div>
|
||||
<div>
|
||||
<div class="app-layout-native-title-bar-actions">
|
||||
<button
|
||||
mat-icon-button
|
||||
class="button app-layout-native-title-bar-minimize"
|
||||
>
|
||||
<!--<mat-icon>minimize</mat-icon>-->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<line x1="5" y1="18" x2="19" y2="18"></line>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
mat-icon-button
|
||||
class="button app-layout-native-title-bar-maximize"
|
||||
>
|
||||
<ng-container [ngSwitch]="'Maximized'">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="round"
|
||||
*ngSwitchCase="'Maximized'"
|
||||
>
|
||||
<path
|
||||
class="st0"
|
||||
d="M15,9.5v7c0,0.8-0.7,1.5-1.5,1.5h-7C5.7,18,5,17.3,5,16.5v-7C5,8.7,5.7,8,6.5,8h7C14.3,8,15,8.7,15,9.5z"
|
||||
/>
|
||||
<path
|
||||
class="st0"
|
||||
d="M8.8,6.8V6c0-0.8,0.7-1.5,1.5-1.5H17c0.8,0,1.5,0.7,1.5,1.5v6.8c0,0.8-0.7,1.5-1.5,1.5h-0.8"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<!--<mat-icon *ngSwitchDefault>crop_din</mat-icon>-->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="round"
|
||||
*ngSwitchDefault
|
||||
>
|
||||
<rect
|
||||
x="5"
|
||||
y="5"
|
||||
width="12"
|
||||
height="12"
|
||||
rx="2"
|
||||
ry="2"
|
||||
></rect>
|
||||
</svg>
|
||||
</ng-container>
|
||||
</button>
|
||||
<button
|
||||
mat-icon-button
|
||||
class="button app-layout-native-title-bar-close"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</mat-toolbar>
|
||||
<div class="contents-main">
|
||||
<div class="subtitle">
|
||||
<mat-toolbar>
|
||||
<mat-toolbar-row>
|
||||
<div class="profileImage">
|
||||
ProfileImage
|
||||
</div>
|
||||
<span>[원조] 프로젝트 방 (<strong>24</strong>)</span>
|
||||
<span class="example-spacer"></span>
|
||||
<button mat-mini-fab color="primary" aria-label="">
|
||||
<mat-icon>search</mat-icon>
|
||||
</button>
|
||||
<button mat-mini-fab color="primary" aria-label="">
|
||||
<mat-icon>alarm</mat-icon>
|
||||
</button>
|
||||
<button mat-mini-fab color="primary" aria-label="">
|
||||
<mat-icon>group</mat-icon>
|
||||
</button>
|
||||
<button
|
||||
mat-mini-fab
|
||||
color="primary"
|
||||
aria-label=""
|
||||
(click)="rightDrawer.toggle()"
|
||||
>
|
||||
<mat-icon>menu</mat-icon>
|
||||
</button>
|
||||
</mat-toolbar-row>
|
||||
</mat-toolbar>
|
||||
</div>
|
||||
<div class="message-area">
|
||||
<mat-drawer-container autosize>
|
||||
<div class="message-container">
|
||||
<div class="chat-area">
|
||||
<div class="others">
|
||||
<dl>
|
||||
<dt>
|
||||
<div class="profileImage">ProfileImage</div>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="name">이선임</span>
|
||||
<span class="date">오전 12:47</span>
|
||||
<button
|
||||
mat-icon-button
|
||||
[matMenuTriggerFor]="menu"
|
||||
aria-label="group menu"
|
||||
>
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
</dt>
|
||||
<dd class="type-text">
|
||||
오전 회의결과 공유해 드려요. 각자 맡은 영역의
|
||||
자료를 취합 후 정리하여 보내주시면 됩니다. 담당자
|
||||
최우영께 문의해 줏세요
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dd class="unread-count">
|
||||
4
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="me">
|
||||
<dl>
|
||||
<dt style="display: none;">
|
||||
<div class="profileImage">ProfileImage</div>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="name" style="display: none;"
|
||||
>내이름</span
|
||||
>
|
||||
<span class="date">오전 12:48</span>
|
||||
<button
|
||||
mat-icon-button
|
||||
[matMenuTriggerFor]="menu"
|
||||
aria-label="group menu"
|
||||
>
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
</dt>
|
||||
<dd class="type-text">
|
||||
오전 외부 지원으로 인해 참석하지 못해 진척사항과
|
||||
함께 보내주신 내용 파악해서 보고 답변
|
||||
드리겠습니다. 혹시 문의할 내용 있으면 다시
|
||||
메신저로 연락드리겠습니다
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dd class="unread-count">
|
||||
4
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="others">
|
||||
<dl>
|
||||
<dt>
|
||||
<div class="profileImage">ProfileImage</div>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="name">김유정</span>
|
||||
<span class="date">오전 12:49</span>
|
||||
<button
|
||||
mat-icon-button
|
||||
[matMenuTriggerFor]="menu"
|
||||
aria-label="group menu"
|
||||
>
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
</dt>
|
||||
<dd class="type-file">
|
||||
파일정보 영역 보여주시고,마우스 오버시
|
||||
오버레이되는 영역의 코딩도
|
||||
부탁드립니다.([min-대화]대화방-일반 참고)
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dd class="unread-count">
|
||||
4
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="others">
|
||||
<dl>
|
||||
<dt>
|
||||
<div class="profileImage">ProfileImage</div>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="name">김유정</span>
|
||||
<span class="date">오전 12:49</span>
|
||||
<button
|
||||
mat-icon-button
|
||||
[matMenuTriggerFor]="menu"
|
||||
aria-label="group menu"
|
||||
>
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
</dt>
|
||||
<dd class="type-translation">
|
||||
<div class="original">
|
||||
오전 회의결과 공유해 드려요. 각자 맡은 영역의
|
||||
자료를 취합 후 정리하여 보내주시면 됩니다.
|
||||
담당자 최우영께 문의해 줏세요
|
||||
</div>
|
||||
<div class="translate">
|
||||
<span class="lang">EN</span>
|
||||
We will share the results of the meeting. You
|
||||
can collect the data of each area and send it
|
||||
together. Please contact Choi Woo-young, the
|
||||
person in charge
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dd class="unread-count">
|
||||
4
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat-form-area">
|
||||
<mat-form-field
|
||||
class="message-text"
|
||||
fxFlex
|
||||
floatLabel="never"
|
||||
appearance="standard"
|
||||
>
|
||||
<textarea
|
||||
matInput
|
||||
#replyInput
|
||||
placeholder=""
|
||||
ngModel
|
||||
name="message"
|
||||
[matTextareaAutosize]="true"
|
||||
[matAutosizeMaxRows]="20"
|
||||
></textarea>
|
||||
</mat-form-field>
|
||||
<div class="button-area">
|
||||
<button mat-icon-button aria-label="">
|
||||
<mat-icon>attach_file</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button aria-label="">
|
||||
<mat-icon>photo_library</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button aria-label="">
|
||||
<mat-icon>control_camera</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button aria-label="">
|
||||
<mat-icon>insert_emoticon</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button aria-label="">
|
||||
<mat-icon>email</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button aria-label="">
|
||||
<mat-icon>g_translate</mat-icon>
|
||||
</button>
|
||||
<button mat-button>+GAMS</button>
|
||||
<button mat-fab color="accent" aria-label="">
|
||||
<mat-icon>send</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<mat-drawer
|
||||
#rightDrawer
|
||||
mode="side"
|
||||
position="end"
|
||||
class="rightDrawer"
|
||||
>
|
||||
Right Sections.
|
||||
</mat-drawer>
|
||||
</mat-drawer-container>
|
||||
</div>
|
||||
</div>
|
||||
</mat-drawer-content>
|
||||
</mat-drawer-container>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<div>
|
||||
<span>현재버전 0.0.11</span>
|
||||
<span>최신버전 0.0.11</span>
|
||||
</div>
|
||||
<div style="right: 0;">
|
||||
HelpDesk 1661-9066
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-menu #menu="matMenu">
|
||||
<button mat-menu-item>Item 1</button>
|
||||
<button mat-menu-item>Item 2</button>
|
||||
</mat-menu>
|
140
src/app/pages/chat/chat.component.scss
Normal file
140
src/app/pages/chat/chat.component.scss
Normal file
|
@ -0,0 +1,140 @@
|
|||
.container {
|
||||
.gnb,
|
||||
.menu-container {
|
||||
float: left;
|
||||
|
||||
.list-section {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.contents-main {
|
||||
.mainProfile {
|
||||
float: left;
|
||||
height: 600px;
|
||||
}
|
||||
|
||||
.info {
|
||||
.allim {
|
||||
.allimList {
|
||||
.allim-card {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
.gnb {
|
||||
.left-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.global-menu {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep .global-menu {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
.mat-tab-header {
|
||||
border-bottom: none !important;
|
||||
width: 100%;
|
||||
}
|
||||
.mat-tab-label-container {
|
||||
.mat-tab-list {
|
||||
.mat-tab-labels {
|
||||
flex-flow: column;
|
||||
height: 360px;
|
||||
padding-top: 10px;
|
||||
border-bottom: none;
|
||||
|
||||
.mat-tab-label {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
padding: 0;
|
||||
min-width: 0 !important;
|
||||
.mat-tab-label-content {
|
||||
.icon-item {
|
||||
display: inline-flex;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
transform: scale(0.9);
|
||||
transition: transform 0.3s cubic-bezier(0.4, 0, 0, 1);
|
||||
|
||||
svg {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
stroke: #ffffff;
|
||||
stroke-width: 1.5;
|
||||
stroke-linecap: square;
|
||||
stroke-linejoin: miter;
|
||||
fill: none;
|
||||
}
|
||||
.mat-badge-content {
|
||||
right: -4px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.mat-tab-label-active {
|
||||
opacity: 0;
|
||||
}
|
||||
&[aria-selected='true'] {
|
||||
opacity: 1;
|
||||
.mat-tab-label-content {
|
||||
.icon-item {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.mat-ink-bar {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.mat-tab-body-wrapper {
|
||||
.mat-tab-body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
div {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.left-drawer-toggle {
|
||||
position: absolute;
|
||||
top: calc(50% - 30px);
|
||||
left: -4px;
|
||||
border: 1px solid #dddddd;
|
||||
background-color: #ffffff !important;
|
||||
width: 24px;
|
||||
height: 60px;
|
||||
border-radius: 0 8px 8px 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
justify-items: center;
|
||||
font-size: 1.8em;
|
||||
z-index: inherit;
|
||||
}
|
||||
|
||||
.example-spacer {
|
||||
flex: 1 1 auto;
|
||||
}
|
25
src/app/pages/chat/chat.component.spec.ts
Normal file
25
src/app/pages/chat/chat.component.spec.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ChatComponent } from './chat.component';
|
||||
|
||||
describe('ChatComponent', () => {
|
||||
let component: ChatComponent;
|
||||
let fixture: ComponentFixture<ChatComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ChatComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ChatComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
24
src/app/pages/chat/chat.component.stories.ts
Normal file
24
src/app/pages/chat/chat.component.stories.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { action } from '@storybook/addon-actions';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
import { moduleMetadata } from '@storybook/angular';
|
||||
import { ChatComponent } from './chat.component';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import { ChatItemComponent } from './component/chat-item.component';
|
||||
|
||||
export default {
|
||||
title: 'ChatComponent',
|
||||
component: ChatComponent,
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
imports: [BrowserModule, BrowserAnimationsModule, MaterialModule],
|
||||
providers: [],
|
||||
declarations: [ChatItemComponent]
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
export const Page = () => ({
|
||||
component: ChatComponent
|
||||
});
|
15
src/app/pages/chat/chat.component.ts
Normal file
15
src/app/pages/chat/chat.component.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-chat',
|
||||
templateUrl: './chat.component.html',
|
||||
styleUrls: ['./chat.component.scss']
|
||||
})
|
||||
export class ChatComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
}
|
10
src/app/pages/chat/chat.module.ts
Normal file
10
src/app/pages/chat/chat.module.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { ChatItemComponent } from './component/chat-item.component';
|
||||
|
||||
const COMPONENT = [ChatItemComponent];
|
||||
|
||||
@NgModule({
|
||||
exports: [...COMPONENT],
|
||||
declarations: [...COMPONENT]
|
||||
})
|
||||
export class ChatModule {}
|
1
src/app/pages/chat/component/chat-item.component.html
Normal file
1
src/app/pages/chat/component/chat-item.component.html
Normal file
|
@ -0,0 +1 @@
|
|||
<p>chat-list works!</p>
|
24
src/app/pages/chat/component/chat-item.component.spec.ts
Normal file
24
src/app/pages/chat/component/chat-item.component.spec.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ChatItemComponent } from './chat-item.component';
|
||||
|
||||
describe('ChatItemComponent', () => {
|
||||
let component: ChatItemComponent;
|
||||
let fixture: ComponentFixture<ChatItemComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ChatItemComponent]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ChatItemComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
12
src/app/pages/chat/component/chat-item.component.ts
Normal file
12
src/app/pages/chat/component/chat-item.component.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-chat-item',
|
||||
templateUrl: './chat-item.component.html',
|
||||
styleUrls: ['./chat-item.component.scss']
|
||||
})
|
||||
export class ChatItemComponent implements OnInit {
|
||||
constructor() {}
|
||||
|
||||
ngOnInit(): void {}
|
||||
}
|
12
src/app/pages/common/common.component.html
Normal file
12
src/app/pages/common/common.component.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<div>
|
||||
<h3>popup components</h3>
|
||||
<button mat-stroked-button color="primary" (click)="openDialog('CHAT')">
|
||||
New-Chat
|
||||
</button>
|
||||
<button mat-stroked-button color="primary" (click)="openDialog('GROUP')">
|
||||
New-Group
|
||||
</button>
|
||||
<button mat-stroked-button color="primary" (click)="openDialog('SETTING')">
|
||||
Setting
|
||||
</button>
|
||||
</div>
|
0
src/app/pages/common/common.component.scss
Normal file
0
src/app/pages/common/common.component.scss
Normal file
25
src/app/pages/common/common.component.spec.ts
Normal file
25
src/app/pages/common/common.component.spec.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CommonComponent } from './common.component';
|
||||
|
||||
describe('CommonComponent', () => {
|
||||
let component: CommonComponent;
|
||||
let fixture: ComponentFixture<CommonComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ CommonComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CommonComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
29
src/app/pages/common/common.component.stories.ts
Normal file
29
src/app/pages/common/common.component.stories.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import { action } from '@storybook/addon-actions';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import { moduleMetadata } from '@storybook/angular';
|
||||
import { CommonComponent } from './common.component';
|
||||
import { NewGroupComponent } from './popup/new-group.component';
|
||||
import { NewChatComponent } from './popup/new-chat.component';
|
||||
import { SettingComponent } from './popup/setting.component';
|
||||
import { DIALOGS } from './popup';
|
||||
import { UserItemComponent } from '../group/component/user-item.component';
|
||||
|
||||
export default {
|
||||
title: '99_Common/CommonComponent',
|
||||
component: CommonComponent,
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
imports: [BrowserModule, BrowserAnimationsModule, MaterialModule],
|
||||
providers: [],
|
||||
declarations: [DIALOGS, UserItemComponent],
|
||||
entryComponents: [DIALOGS]
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
export const Page = () => ({
|
||||
component: CommonComponent
|
||||
});
|
39
src/app/pages/common/common.component.ts
Normal file
39
src/app/pages/common/common.component.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { NewChatComponent } from './popup/new-chat.component';
|
||||
import { NewGroupComponent } from './popup/new-group.component';
|
||||
import { SettingComponent } from './popup/setting.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-common',
|
||||
templateUrl: './common.component.html',
|
||||
styleUrls: ['./common.component.scss']
|
||||
})
|
||||
export class CommonComponent implements OnInit {
|
||||
constructor(public dialog: MatDialog) {}
|
||||
|
||||
ngOnInit(): void {}
|
||||
|
||||
openDialog(type: string): void {
|
||||
switch (type) {
|
||||
case 'CHAT':
|
||||
this.dialog.open(NewChatComponent, {
|
||||
width: '850px',
|
||||
data: {}
|
||||
});
|
||||
break;
|
||||
case 'GROUP':
|
||||
this.dialog.open(NewGroupComponent, {
|
||||
width: '250px',
|
||||
data: {}
|
||||
});
|
||||
break;
|
||||
case 'SETTING':
|
||||
this.dialog.open(SettingComponent, {
|
||||
width: '250px',
|
||||
data: {}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
14
src/app/pages/common/common.module.ts
Normal file
14
src/app/pages/common/common.module.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { NewGroupComponent } from './popup/new-group.component';
|
||||
import { NewChatComponent } from './popup/new-chat.component';
|
||||
import { SettingComponent } from './popup/setting.component';
|
||||
import { DIALOGS } from './popup';
|
||||
|
||||
const COMPONENT = [];
|
||||
|
||||
@NgModule({
|
||||
exports: [...COMPONENT, DIALOGS],
|
||||
declarations: [...COMPONENT, DIALOGS],
|
||||
entryComponents: [...COMPONENT, DIALOGS]
|
||||
})
|
||||
export class CommonModule {}
|
14
src/app/pages/common/loading.component.html
Normal file
14
src/app/pages/common/loading.component.html
Normal file
|
@ -0,0 +1,14 @@
|
|||
<div
|
||||
fxLayout="column"
|
||||
fxLayoutAlign="space-between center"
|
||||
style="
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
place-content: center space-around;
|
||||
align-items: center;
|
||||
"
|
||||
>
|
||||
loading
|
||||
</div>
|
0
src/app/pages/common/loading.component.scss
Normal file
0
src/app/pages/common/loading.component.scss
Normal file
24
src/app/pages/common/loading.component.spec.ts
Normal file
24
src/app/pages/common/loading.component.spec.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LoadingComponent } from './loading.component';
|
||||
|
||||
describe('LoadingComponent', () => {
|
||||
let component: LoadingComponent;
|
||||
let fixture: ComponentFixture<LoadingComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [LoadingComponent]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(LoadingComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
22
src/app/pages/common/loading.component.stories.ts
Normal file
22
src/app/pages/common/loading.component.stories.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { action } from '@storybook/addon-actions';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
import { moduleMetadata } from '@storybook/angular';
|
||||
import { LoadingComponent } from './loading.component';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
|
||||
export default {
|
||||
title: '99_Common/LoadingComponent',
|
||||
component: LoadingComponent,
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
imports: [BrowserModule, BrowserAnimationsModule, MaterialModule],
|
||||
providers: []
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
export const Page = () => ({
|
||||
component: LoadingComponent
|
||||
});
|
12
src/app/pages/common/loading.component.ts
Normal file
12
src/app/pages/common/loading.component.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-group',
|
||||
templateUrl: './loading.component.html',
|
||||
styleUrls: ['./loading.component.scss']
|
||||
})
|
||||
export class LoadingComponent implements OnInit {
|
||||
constructor() {}
|
||||
|
||||
ngOnInit(): void {}
|
||||
}
|
5
src/app/pages/common/popup/index.ts
Normal file
5
src/app/pages/common/popup/index.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
import { NewGroupComponent } from './new-group.component';
|
||||
import { NewChatComponent } from './new-chat.component';
|
||||
import { SettingComponent } from './setting.component';
|
||||
|
||||
export const DIALOGS = [NewGroupComponent, NewChatComponent, SettingComponent];
|
137
src/app/pages/common/popup/new-chat.component.html
Normal file
137
src/app/pages/common/popup/new-chat.component.html
Normal file
|
@ -0,0 +1,137 @@
|
|||
<mat-card class="confirm-card mat-elevation-z dialog-creat-chat">
|
||||
<mat-card-header>
|
||||
<mat-card-title cdkDrag cdkDragRootElement=".cdk-overlay-pane" cdkDragHandle
|
||||
>새 대화추가</mat-card-title
|
||||
>
|
||||
<button class="icon-button btn-dialog-close">
|
||||
<i class="mdi mdi-window-close"></i>
|
||||
</button>
|
||||
</mat-card-header>
|
||||
|
||||
<mat-card-content>
|
||||
<div
|
||||
fxLayout="column"
|
||||
fxLayout.xs="column"
|
||||
fxLayoutAlign="center"
|
||||
fxLayoutGap="10px"
|
||||
fxLayoutGap.xs="0"
|
||||
class="mat-card-content-frame"
|
||||
>
|
||||
<div fxFlex class="container">
|
||||
<!-- search-->
|
||||
<div>
|
||||
검색창
|
||||
</div>
|
||||
<mat-tab-group mat-stretch-tabs>
|
||||
<!--그룹-->
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<!-- <button class="icon-button">
|
||||
<i class="mid mid-24 mdi-account-multiple"></i>
|
||||
</button> -->
|
||||
<p>그룹</p>
|
||||
</ng-template>
|
||||
<div fxFlexFill>
|
||||
<div class="mat-tab-frame dialog-tab-grouplist">
|
||||
<div class="list">
|
||||
<mat-accordion>
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
즐겨찾기
|
||||
<span>(<strong>6</strong>/7)</span>
|
||||
</mat-panel-title>
|
||||
<mat-panel-description></mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
<app-user-item [check]="true"> </app-user-item>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
</mat-expansion-panel>
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
그룹명을 넣습니다
|
||||
<span>(<strong>6</strong>/7)</span>
|
||||
</mat-panel-title>
|
||||
<mat-panel-description> </mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
<app-user-item [check]="true"></app-user-item>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-tab>
|
||||
<!--조직-->
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<!-- <button class="icon-button">
|
||||
<i class="mid mid-24 mdi-account-multiple"></i>
|
||||
</button> -->
|
||||
<p>조직도</p>
|
||||
</ng-template>
|
||||
<div fxFlexFill>
|
||||
<div class="mat-tab-frame dialog-tab-grouplist">
|
||||
<div><!-- group -->ffffffffff</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<ng-template #selectedUserListTemplate>
|
||||
<div class="list-chip">
|
||||
<mat-chip-list aria-label="User selection">
|
||||
<mat-chip *ngFor="let userInfo of selectedUserList" [selected]="true">
|
||||
김선규
|
||||
<mat-icon matChipRemove *ngIf="true">clear</mat-icon>
|
||||
</mat-chip>
|
||||
</mat-chip-list>
|
||||
</div>
|
||||
<ng-container
|
||||
*ngIf="
|
||||
data.type === UserSelectDialogType.NewChat;
|
||||
then newchatcount;
|
||||
else defaultcount
|
||||
"
|
||||
></ng-container>
|
||||
<ng-template #newchatcount>
|
||||
<span
|
||||
[ngClass]="
|
||||
selectedUserList.length >=
|
||||
environment.productConfig.CommonSetting.maxChatRoomUser
|
||||
? 'text-warn-color'
|
||||
: ''
|
||||
"
|
||||
>
|
||||
13 / 21 명
|
||||
</span>
|
||||
<span
|
||||
class="text-warn-color"
|
||||
style="float: right;"
|
||||
*ngIf="selectedUserList.length >= 50"
|
||||
>
|
||||
에러
|
||||
</span>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
</mat-card>
|
178
src/app/pages/common/popup/new-chat.component.scss
Normal file
178
src/app/pages/common/popup/new-chat.component.scss
Normal file
|
@ -0,0 +1,178 @@
|
|||
.dialog-creat-chat {
|
||||
height: 100%;
|
||||
& > .mat-card-header {
|
||||
.btn-dialog-close {
|
||||
font-size: 20px;
|
||||
display: flex;
|
||||
margin-left: auto;
|
||||
align-self: flex-start;
|
||||
color: #444444;
|
||||
}
|
||||
}
|
||||
& > .mat-card-content {
|
||||
position: relative;
|
||||
.mat-card-content-frame {
|
||||
height: calc(100% - 50px);
|
||||
.container {
|
||||
height: 100%;
|
||||
.container-frame {
|
||||
height: 530px;
|
||||
}
|
||||
}
|
||||
}
|
||||
//그룹이름 폼 있는 경우
|
||||
.newgroup-form {
|
||||
height: 70px;
|
||||
& + .mat-card-content-frame {
|
||||
height: calc(100% - 120px);
|
||||
.container {
|
||||
.mat-tab-frame {
|
||||
.mat-tab-group {
|
||||
& > .mat-tab-body {
|
||||
height: 380px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
& > .mat-tab-body-wrapper {
|
||||
height: calc(100% - 50px);
|
||||
.mat-tag-body {
|
||||
& > .dialog-tab-orglist {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-tab-grouplist {
|
||||
height: calc(100% - 130px);
|
||||
width: 100%;
|
||||
.group,
|
||||
.search-result {
|
||||
width: 100%;
|
||||
height: calc(100% - 50px);
|
||||
&-expansion {
|
||||
.list-item {
|
||||
height: 60px;
|
||||
}
|
||||
}
|
||||
&-list-item {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*::ng-deep .dialog-tab-chatlist {
|
||||
height: 508px;
|
||||
width: 100%;
|
||||
.chat {
|
||||
width: 100%;
|
||||
}
|
||||
.chat.checkbox {
|
||||
& > .list-item {
|
||||
padding: 0 10px;
|
||||
.item-default {
|
||||
width: calc(100% - 30px);
|
||||
}
|
||||
.mat-badge {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
::ng-deep .dialog-tab-orglist {
|
||||
width: 100%;
|
||||
height: calc(100% - 130px);
|
||||
border-bottom: 1px solid #dddddd;
|
||||
position: relative;
|
||||
.oraganization {
|
||||
.ps__rail-y {
|
||||
left: auto !important;
|
||||
}
|
||||
&-tab {
|
||||
width: 100%;
|
||||
height: calc(100% - 50px);
|
||||
position: relative;
|
||||
&-tree {
|
||||
display: inline-flex;
|
||||
width: 50%;
|
||||
height: 100% !important;
|
||||
border-right: 1px solid #dddddd;
|
||||
overflow: auto;
|
||||
.tab-tree-frame {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.select-list {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
width: 50%;
|
||||
height: 100% !important;
|
||||
overflow: auto;
|
||||
.search-list {
|
||||
overflow: auto;
|
||||
height: calc(100% - 40px);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-chip {
|
||||
height: 100px;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border: 1px solid #dddddd;
|
||||
overflow: auto;
|
||||
background-color: #f9f9f9;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.mat-chip.mat-standard-chip .mat-chip-remove {
|
||||
}
|
||||
|
||||
.confirm-card {
|
||||
.mat-card-content {
|
||||
.content-box {
|
||||
flex-direction: column;
|
||||
flex-flow: column;
|
||||
}
|
||||
}
|
||||
.button-form {
|
||||
text-align: right;
|
||||
.mat-primary {
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*::ng-deep .dialog-creat-chat {
|
||||
& > .mat-tab-body-wrapper {
|
||||
.mat-tab-body {
|
||||
height: 380px;
|
||||
&:nth-child(3) {
|
||||
height: 480px;
|
||||
}
|
||||
.mat-tab-body-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
.mat-card-content {
|
||||
.mat-card-content-frame {
|
||||
height: 100%;
|
||||
.container {
|
||||
height: 100%;
|
||||
.mat-tab-group {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
25
src/app/pages/common/popup/new-chat.component.spec.ts
Normal file
25
src/app/pages/common/popup/new-chat.component.spec.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { NewChatComponent } from './new-chat.component';
|
||||
|
||||
describe('NewChatComponent', () => {
|
||||
let component: NewChatComponent;
|
||||
let fixture: ComponentFixture<NewChatComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ NewChatComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(NewChatComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
19
src/app/pages/common/popup/new-chat.component.ts
Normal file
19
src/app/pages/common/popup/new-chat.component.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import { Component, OnInit, Inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
|
||||
@Component({
|
||||
selector: 'app-new-chat',
|
||||
templateUrl: './new-chat.component.html',
|
||||
styleUrls: ['./new-chat.component.scss']
|
||||
})
|
||||
export class NewChatComponent implements OnInit {
|
||||
selectedUserList: any[] = [
|
||||
{ name: '김선구' },
|
||||
{ name: '김선구1' },
|
||||
{ name: '김선구2' },
|
||||
{ name: '김선구3' }
|
||||
];
|
||||
constructor(@Inject(MAT_DIALOG_DATA) public data: any) {}
|
||||
|
||||
ngOnInit(): void {}
|
||||
}
|
1
src/app/pages/common/popup/new-group.component.html
Normal file
1
src/app/pages/common/popup/new-group.component.html
Normal file
|
@ -0,0 +1 @@
|
|||
<p>new-group works!</p>
|
0
src/app/pages/common/popup/new-group.component.scss
Normal file
0
src/app/pages/common/popup/new-group.component.scss
Normal file
25
src/app/pages/common/popup/new-group.component.spec.ts
Normal file
25
src/app/pages/common/popup/new-group.component.spec.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { NewGroupComponent } from './new-group.component';
|
||||
|
||||
describe('NewGroupComponent', () => {
|
||||
let component: NewGroupComponent;
|
||||
let fixture: ComponentFixture<NewGroupComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ NewGroupComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(NewGroupComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
15
src/app/pages/common/popup/new-group.component.ts
Normal file
15
src/app/pages/common/popup/new-group.component.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-new-group',
|
||||
templateUrl: './new-group.component.html',
|
||||
styleUrls: ['./new-group.component.scss']
|
||||
})
|
||||
export class NewGroupComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
}
|
1
src/app/pages/common/popup/setting.component.html
Normal file
1
src/app/pages/common/popup/setting.component.html
Normal file
|
@ -0,0 +1 @@
|
|||
<p>setting works!</p>
|
0
src/app/pages/common/popup/setting.component.scss
Normal file
0
src/app/pages/common/popup/setting.component.scss
Normal file
25
src/app/pages/common/popup/setting.component.spec.ts
Normal file
25
src/app/pages/common/popup/setting.component.spec.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { SettingComponent } from './setting.component';
|
||||
|
||||
describe('SettingComponent', () => {
|
||||
let component: SettingComponent;
|
||||
let fixture: ComponentFixture<SettingComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ SettingComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SettingComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
15
src/app/pages/common/popup/setting.component.ts
Normal file
15
src/app/pages/common/popup/setting.component.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-setting',
|
||||
templateUrl: './setting.component.html',
|
||||
styleUrls: ['./setting.component.scss']
|
||||
})
|
||||
export class SettingComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
}
|
21
src/app/pages/group/component/user-item.component.html
Normal file
21
src/app/pages/group/component/user-item.component.html
Normal file
|
@ -0,0 +1,21 @@
|
|||
<div class="user-list">
|
||||
<span class="presence">bullet</span>
|
||||
<div class="profileImage">
|
||||
ProfileImage
|
||||
</div>
|
||||
<div class="userInfo">
|
||||
<div>
|
||||
<div class="name">홍길동</div>
|
||||
<div class="grade">대리</div>
|
||||
</div>
|
||||
<div class="deptName">
|
||||
영업팀
|
||||
</div>
|
||||
</div>
|
||||
<div class="intro">
|
||||
맑은 산속 옹달샘 누가와서 먹나요??
|
||||
</div>
|
||||
<div *ngIf="check">
|
||||
<mat-checkbox></mat-checkbox>
|
||||
</div>
|
||||
</div>
|
25
src/app/pages/group/component/user-item.component.spec.ts
Normal file
25
src/app/pages/group/component/user-item.component.spec.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { UserItemComponent } from './user-item.component';
|
||||
|
||||
describe('UserItemComponent', () => {
|
||||
let component: UserItemComponent;
|
||||
let fixture: ComponentFixture<UserItemComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ UserItemComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(UserItemComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
15
src/app/pages/group/component/user-item.component.ts
Normal file
15
src/app/pages/group/component/user-item.component.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { Component, OnInit, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-user-item',
|
||||
templateUrl: './user-item.component.html',
|
||||
styleUrls: ['./user-item.component.scss']
|
||||
})
|
||||
export class UserItemComponent implements OnInit {
|
||||
@Input()
|
||||
check = false;
|
||||
|
||||
constructor() {}
|
||||
|
||||
ngOnInit(): void {}
|
||||
}
|
461
src/app/pages/group/group.component.html
Normal file
461
src/app/pages/group/group.component.html
Normal file
|
@ -0,0 +1,461 @@
|
|||
<div class="container">
|
||||
<div class="gnb">
|
||||
<mat-toolbar><span class="lgucap-logo blind">Logo</span></mat-toolbar>
|
||||
<mat-tab-group
|
||||
mat-stretch-tabs
|
||||
animationDuration="0ms"
|
||||
backgroundColor="transparent"
|
||||
class="global-menu"
|
||||
>
|
||||
<mat-tab aria-label="Group">
|
||||
<ng-template mat-tab-label>
|
||||
<div class="icon-item" matTooltip="그룹" matTooltipPosition="after">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
|
||||
<circle cx="12" cy="7" r="4"></circle>
|
||||
</svg>
|
||||
</div>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
<mat-tab aria-label="Chat">
|
||||
<ng-template mat-tab-label>
|
||||
<div
|
||||
class="icon-item"
|
||||
matBadgeHidden="false"
|
||||
matBadge="275"
|
||||
matBadgeColor="accent"
|
||||
matBadgePosition="above after"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="#000000"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="bevel"
|
||||
>
|
||||
<path
|
||||
d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
<mat-tab aria-label="Organization">
|
||||
<ng-template mat-tab-label>
|
||||
<div class="icon-item">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="#000000"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="bevel"
|
||||
>
|
||||
<circle class="st0" cx="18.4" cy="18.5" r="3" />
|
||||
<circle class="st0" cx="12" cy="5" r="3" />
|
||||
<path class="st0" d="M12.4,10.5h4c1.1,0,2,0.9,2,2v3" />
|
||||
<circle class="st0" cx="6.1" cy="18.5" r="3" />
|
||||
<path class="st0" d="M6.1,15.5v-3c0-1.1,0.9-2,2-2h4" />
|
||||
<line class="st0" x1="12" y1="8" x2="12" y2="9" />
|
||||
</svg>
|
||||
</div>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
|
||||
<mat-tab aria-label="Message">
|
||||
<ng-template mat-tab-label>
|
||||
<div class="icon-item">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="#000000"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="bevel"
|
||||
>
|
||||
<polygon
|
||||
points="21.368 12.001 3 21.609 3 14 11 12 3 9.794 3 2.394"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</div>
|
||||
|
||||
<div class="menu-container">
|
||||
<div class="contents">
|
||||
<mat-drawer-container class="example-container">
|
||||
<mat-drawer #drawer mode="side" opened class="m-messenger-area">
|
||||
<mat-toolbar class="m-messenger-tit">
|
||||
<div>M Messenger</div>
|
||||
<div></div>
|
||||
</mat-toolbar>
|
||||
<div class="list-section">
|
||||
<div class="title-section">
|
||||
<div class="title">
|
||||
<h3>그룹</h3>
|
||||
<div class="btn-box">
|
||||
<button
|
||||
mat-icon-button
|
||||
[matMenuTriggerFor]="menu"
|
||||
aria-label="group menu"
|
||||
>
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="search-area">
|
||||
<mat-select placeholder="선택">
|
||||
<mat-option value="1">1</mat-option>
|
||||
<mat-option value="1">1A</mat-option>
|
||||
<mat-option value="1">1AB</mat-option>
|
||||
<mat-option value="1">1ABCDEFGHIJKLMNOPQRSTUVWXYZ</mat-option>
|
||||
</mat-select>
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label>이름 부서명, 전화번호, 이메일</mat-label>
|
||||
<input
|
||||
matInput
|
||||
placeholder="이름 부서명, 전화번호, 이메일"
|
||||
value=""
|
||||
/>
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<app-user-item class="myProfile"></app-user-item>
|
||||
</div>
|
||||
<div class="list">
|
||||
<mat-accordion>
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
즐겨찾기
|
||||
<span>(<strong>6</strong>/7)</span>
|
||||
</mat-panel-title>
|
||||
<mat-panel-description></mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
<app-user-item></app-user-item>
|
||||
<app-user-item></app-user-item>
|
||||
<app-user-item></app-user-item>
|
||||
<app-user-item></app-user-item>
|
||||
<app-user-item></app-user-item>
|
||||
<app-user-item></app-user-item>
|
||||
<app-user-item></app-user-item>
|
||||
<app-user-item></app-user-item>
|
||||
<app-user-item></app-user-item>
|
||||
<app-user-item></app-user-item>
|
||||
<app-user-item></app-user-item>
|
||||
</mat-expansion-panel>
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
그룹명을 넣습니다
|
||||
<span>(<strong>6</strong>/7)</span>
|
||||
</mat-panel-title>
|
||||
<mat-panel-description> </mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
<app-user-item></app-user-item>
|
||||
<app-user-item></app-user-item>
|
||||
<app-user-item></app-user-item>
|
||||
<app-user-item></app-user-item>
|
||||
<app-user-item></app-user-item>
|
||||
<app-user-item></app-user-item>
|
||||
<app-user-item></app-user-item>
|
||||
<app-user-item></app-user-item>
|
||||
<app-user-item></app-user-item>
|
||||
<app-user-item></app-user-item>
|
||||
<app-user-item></app-user-item>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
</div>
|
||||
</div>
|
||||
</mat-drawer>
|
||||
<mat-drawer-content class="drawer-content">
|
||||
<button
|
||||
mat-icon-button
|
||||
class="left-drawer-toggle"
|
||||
(click)="drawer.toggle()"
|
||||
>
|
||||
<
|
||||
</button>
|
||||
<mat-toolbar>
|
||||
<div><span>Today</span>2020.05.05</div>
|
||||
<div>
|
||||
<div class="app-layout-native-title-bar-actions">
|
||||
<button
|
||||
mat-icon-button
|
||||
class="button app-layout-native-title-bar-minimize"
|
||||
>
|
||||
<!--<mat-icon>minimize</mat-icon>-->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<line x1="5" y1="18" x2="19" y2="18"></line>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
mat-icon-button
|
||||
class="button app-layout-native-title-bar-maximize"
|
||||
>
|
||||
<ng-container [ngSwitch]="'Maximized'">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="round"
|
||||
*ngSwitchCase="'Maximized'"
|
||||
>
|
||||
<path
|
||||
class="st0"
|
||||
d="M15,9.5v7c0,0.8-0.7,1.5-1.5,1.5h-7C5.7,18,5,17.3,5,16.5v-7C5,8.7,5.7,8,6.5,8h7C14.3,8,15,8.7,15,9.5z"
|
||||
/>
|
||||
<path
|
||||
class="st0"
|
||||
d="M8.8,6.8V6c0-0.8,0.7-1.5,1.5-1.5H17c0.8,0,1.5,0.7,1.5,1.5v6.8c0,0.8-0.7,1.5-1.5,1.5h-0.8"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<!--<mat-icon *ngSwitchDefault>crop_din</mat-icon>-->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="round"
|
||||
*ngSwitchDefault
|
||||
>
|
||||
<rect
|
||||
x="5"
|
||||
y="5"
|
||||
width="12"
|
||||
height="12"
|
||||
rx="2"
|
||||
ry="2"
|
||||
></rect>
|
||||
</svg>
|
||||
</ng-container>
|
||||
</button>
|
||||
<button
|
||||
mat-icon-button
|
||||
class="button app-layout-native-title-bar-close"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</mat-toolbar>
|
||||
<div class="contents-main">
|
||||
<div class="subtitle">Welcome to M-Messenger</div>
|
||||
<div class="mainProfile">
|
||||
<mat-card class="example-card">
|
||||
<mat-card-header>
|
||||
<div
|
||||
mat-card-avatar
|
||||
class="profileImage"
|
||||
style="background-size: cover;"
|
||||
>
|
||||
<img
|
||||
src="https://material.angular.io/assets/img/examples/shiba2.jpg"
|
||||
style="width: 50px; height: auto;"
|
||||
/>
|
||||
</div>
|
||||
<mat-card-title>홍길동 <span>선임</span></mat-card-title>
|
||||
<mat-card-subtitle>(Hong Gil Dong)</mat-card-subtitle>
|
||||
<mat-card-subtitle><span>O</span>온라인</mat-card-subtitle>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<div class="intro">
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label>이름 부서명, 전화번호, 이메일</mat-label>
|
||||
<input
|
||||
matInput
|
||||
placeholder="이름 부서명, 전화번호, 이메일"
|
||||
value=""
|
||||
/>
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<ul>
|
||||
<li class="company"><label>회사</label>LGCNS</li>
|
||||
<li class="dept"><label>부서</label>아키텍쳐 솔루션</li>
|
||||
<li class="email"><label>이메일</label>lgcns@gmail.com</li>
|
||||
<li class="office">
|
||||
<label>사무실</label>+82) 041-111-2222
|
||||
</li>
|
||||
<li class="mobile"><label>모바일</label>031-2222-4444</li>
|
||||
</ul>
|
||||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
<button mat-button class="info">info</button>
|
||||
<button mat-button class="theme">theme1</button>
|
||||
<button mat-button class="theme">theme2</button>
|
||||
<button mat-button class="theme checked">theme3</button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="bookmark">
|
||||
<div class="subtitle">Bookmark</div>
|
||||
<div class="chatlist">
|
||||
<!-- loop > component > 대화 리스트 공용 -->
|
||||
<div>
|
||||
<div class="profileImage">
|
||||
<img
|
||||
src="https://material.angular.io/assets/img/examples/shiba2.jpg"
|
||||
style="width: 50px; height: 50px;"
|
||||
/>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="roomName">UCAP 프로젝트방</div>
|
||||
<div class="lastMessage">
|
||||
대화방의 마지막대화내용이 들어갈껍니다.
|
||||
</div>
|
||||
</div>
|
||||
<div class="subInfo">
|
||||
<div class="lastDate" matBadge="4">2020.04.05</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--// loop > component > 대화 리스트 공용 -->
|
||||
<div>
|
||||
<div class="profileImage">
|
||||
<img
|
||||
src="https://material.angular.io/assets/img/examples/shiba2.jpg"
|
||||
style="width: 50px; height: 50px;"
|
||||
/>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="roomName">UCAP 프로젝트방</div>
|
||||
<div class="lastMessage">
|
||||
대화방의 마지막대화내용이 들어갈껍니다.
|
||||
</div>
|
||||
</div>
|
||||
<div class="subInfo">
|
||||
<div class="lastDate">2020.04.05</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="allim">
|
||||
<div class="subtitle">알림봇</div>
|
||||
<div class="allimList">
|
||||
<mat-card class="allim-card">
|
||||
<mat-card-header>
|
||||
<div
|
||||
mat-card-avatar
|
||||
class="profileImage"
|
||||
style="background-size: cover;"
|
||||
>
|
||||
<img
|
||||
src="https://material.angular.io/assets/img/examples/shiba2.jpg"
|
||||
style="width: 50px; height: auto;"
|
||||
/>
|
||||
</div>
|
||||
<mat-card-title>화상회의</mat-card-title>
|
||||
<mat-card-subtitle>2020.04.05</mat-card-subtitle>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<div class="title">화상회의 개설</div>
|
||||
<div class="contents">화상회의가 개설되었습니다.</div>
|
||||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
<button mat-button class="more">더보기</button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
<mat-card class="allim-card">
|
||||
<mat-card-header>
|
||||
<div
|
||||
mat-card-avatar
|
||||
class="profileImage"
|
||||
style="background-size: cover;"
|
||||
>
|
||||
<img
|
||||
src="https://material.angular.io/assets/img/examples/shiba2.jpg"
|
||||
style="width: 50px; height: auto;"
|
||||
/>
|
||||
</div>
|
||||
<mat-card-title>화상회의</mat-card-title>
|
||||
<mat-card-subtitle>2020.04.05</mat-card-subtitle>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<div class="title">화상회의 개설</div>
|
||||
<div class="contents">화상회의가 개설되었습니다.</div>
|
||||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
<button mat-button class="more">더보기</button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
<div class="banner">배너</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-drawer-content>
|
||||
</mat-drawer-container>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<div>
|
||||
<span>현재버전 0.0.11</span>
|
||||
<span>최신버전 0.0.11</span>
|
||||
</div>
|
||||
<div style="right: 0;">
|
||||
HelpDesk 1661-9066
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-menu #menu="matMenu">
|
||||
<button mat-menu-item>Item 1</button>
|
||||
<button mat-menu-item>Item 2</button>
|
||||
</mat-menu>
|
185
src/app/pages/group/group.component.scss
Normal file
185
src/app/pages/group/group.component.scss
Normal file
|
@ -0,0 +1,185 @@
|
|||
@charset 'UTF-8';
|
||||
|
||||
@import '../../../assets/scss/components.scss';
|
||||
|
||||
.container {
|
||||
@extend %clearfix;
|
||||
@extend %guideline; //Guide Line
|
||||
background-color: $gray-ref0;
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
.gnb,
|
||||
.menu-container {
|
||||
float: left;
|
||||
|
||||
.list-section {
|
||||
margin-top: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
.contents-main {
|
||||
@extend %clearfix;
|
||||
height: calc(100vh - 122px);
|
||||
.mainProfile {
|
||||
float: left;
|
||||
height: 600px;
|
||||
}
|
||||
|
||||
.info {
|
||||
.allim {
|
||||
.allimList {
|
||||
.allim-card {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
@extend %clearfix;
|
||||
height: 40px;
|
||||
width: 100%;
|
||||
@extend %guideline; //Guide Line
|
||||
}
|
||||
}
|
||||
|
||||
.gnb {
|
||||
@extend %guideline; //Guide Line
|
||||
background-color: $gray-ref0;
|
||||
width: 60px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.lgucap-logo {
|
||||
display: block;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background: url(../../../assets/images/logo_140.png) no-repeat 50% 0;
|
||||
background-size: 32px;
|
||||
}
|
||||
|
||||
.left-container {
|
||||
display: flex;
|
||||
width: calc(100% - 28px);
|
||||
height: 100%;
|
||||
}
|
||||
.global-menu {
|
||||
width: 100%;
|
||||
background-color: $gray-ref0;
|
||||
}
|
||||
|
||||
::ng-deep .global-menu {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
.mat-tab-header {
|
||||
border-bottom: none !important;
|
||||
width: 100%;
|
||||
}
|
||||
.mat-tab-label-container {
|
||||
.mat-tab-list {
|
||||
.mat-tab-labels {
|
||||
@extend %clearfix;
|
||||
flex-flow: column;
|
||||
height: 100vh;
|
||||
padding-top: 10px;
|
||||
border-bottom: none;
|
||||
|
||||
.mat-tab-label {
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
padding: 0;
|
||||
min-width: 0 !important;
|
||||
.mat-tab-label-content {
|
||||
.icon-item {
|
||||
display: inline-flex;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
transform: scale(0.9);
|
||||
transition: transform 0.3s cubic-bezier(0.4, 0, 0, 1);
|
||||
|
||||
svg {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
stroke: #ffffff;
|
||||
stroke-width: 1.5;
|
||||
stroke-linecap: square;
|
||||
stroke-linejoin: miter;
|
||||
fill: none;
|
||||
}
|
||||
.mat-badge-content {
|
||||
right: -4px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.mat-tab-label-active {
|
||||
opacity: 0;
|
||||
}
|
||||
&[aria-selected='true'] {
|
||||
opacity: 1;
|
||||
.mat-tab-label-content {
|
||||
.icon-item {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.mat-ink-bar {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.mat-tab-body-wrapper {
|
||||
.mat-tab-body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu-container {
|
||||
@extend %clearfix;
|
||||
@extend %guideline2; //Guide Line2
|
||||
width: calc(100% - 71px);
|
||||
@extend %height100vh;
|
||||
box-sizing: border-box;
|
||||
.m-messenger-area {
|
||||
width: 400px;
|
||||
padding-top: 50px;
|
||||
box-shadow: 1px 2px 3px rgba(0, 0, 0, 0.6);
|
||||
.m-messenger-tit {
|
||||
width: 400px;
|
||||
height: 50px;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
@extend %clearfix;
|
||||
div {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.left-drawer-toggle {
|
||||
position: absolute;
|
||||
top: calc(50% - 30px);
|
||||
left: -4px;
|
||||
border: 1px solid #dddddd;
|
||||
background-color: #ffffff !important;
|
||||
width: 24px;
|
||||
height: 60px;
|
||||
border-radius: 0 8px 8px 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
justify-items: center;
|
||||
font-size: 1.8em;
|
||||
z-index: inherit;
|
||||
}
|
25
src/app/pages/group/group.component.spec.ts
Normal file
25
src/app/pages/group/group.component.spec.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { GroupComponent } from './group.component';
|
||||
|
||||
describe('GroupComponent', () => {
|
||||
let component: GroupComponent;
|
||||
let fixture: ComponentFixture<GroupComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ GroupComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(GroupComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
24
src/app/pages/group/group.component.stories.ts
Normal file
24
src/app/pages/group/group.component.stories.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { action } from '@storybook/addon-actions';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
import { moduleMetadata } from '@storybook/angular';
|
||||
import { GroupComponent } from './group.component';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import { UserItemComponent } from './component/user-item.component';
|
||||
|
||||
export default {
|
||||
title: 'GroupComponent',
|
||||
component: GroupComponent,
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
imports: [BrowserModule, BrowserAnimationsModule, MaterialModule],
|
||||
providers: [],
|
||||
declarations: [UserItemComponent]
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
export const Page = () => ({
|
||||
component: GroupComponent
|
||||
});
|
15
src/app/pages/group/group.component.ts
Normal file
15
src/app/pages/group/group.component.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-group',
|
||||
templateUrl: './group.component.html',
|
||||
styleUrls: ['./group.component.scss']
|
||||
})
|
||||
export class GroupComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
}
|
10
src/app/pages/group/group.module.ts
Normal file
10
src/app/pages/group/group.module.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { UserItemComponent } from './component/user-item.component';
|
||||
|
||||
const COMPONENT = [UserItemComponent];
|
||||
|
||||
@NgModule({
|
||||
exports: [...COMPONENT],
|
||||
declarations: [...COMPONENT]
|
||||
})
|
||||
export class GroupModule {}
|
1
src/app/pages/message/message.component.html
Normal file
1
src/app/pages/message/message.component.html
Normal file
|
@ -0,0 +1 @@
|
|||
<p>message works!</p>
|
0
src/app/pages/message/message.component.scss
Normal file
0
src/app/pages/message/message.component.scss
Normal file
25
src/app/pages/message/message.component.spec.ts
Normal file
25
src/app/pages/message/message.component.spec.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MessageComponent } from './message.component';
|
||||
|
||||
describe('MessageComponent', () => {
|
||||
let component: MessageComponent;
|
||||
let fixture: ComponentFixture<MessageComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ MessageComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(MessageComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
22
src/app/pages/message/message.component.stories.ts
Normal file
22
src/app/pages/message/message.component.stories.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { action } from '@storybook/addon-actions';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
import { moduleMetadata } from '@storybook/angular';
|
||||
import { MessageComponent } from './message.component';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
|
||||
export default {
|
||||
title: 'MessageComponent',
|
||||
component: MessageComponent,
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
imports: [BrowserModule, BrowserAnimationsModule, MaterialModule],
|
||||
providers: []
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
export const Page = () => ({
|
||||
component: MessageComponent
|
||||
});
|
15
src/app/pages/message/message.component.ts
Normal file
15
src/app/pages/message/message.component.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-message',
|
||||
templateUrl: './message.component.html',
|
||||
styleUrls: ['./message.component.scss']
|
||||
})
|
||||
export class MessageComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
}
|
624
src/app/pages/organization/component/animation.ts
Normal file
624
src/app/pages/organization/component/animation.ts
Normal file
|
@ -0,0 +1,624 @@
|
|||
import {
|
||||
sequence,
|
||||
trigger,
|
||||
animate,
|
||||
style,
|
||||
group,
|
||||
query,
|
||||
transition,
|
||||
animateChild,
|
||||
state,
|
||||
animation,
|
||||
useAnimation,
|
||||
stagger,
|
||||
keyframes
|
||||
} from '@angular/animations';
|
||||
|
||||
const customAnimation = animation(
|
||||
[
|
||||
style({
|
||||
opacity: '{{opacity}}',
|
||||
transform: 'scale({{scale}}) translate3d({{x}}, {{y}}, {{z}})'
|
||||
}),
|
||||
animate('{{duration}} {{delay}} cubic-bezier(0.0, 0.0, 0.2, 1)', style('*'))
|
||||
],
|
||||
{
|
||||
params: {
|
||||
duration: '200ms',
|
||||
delay: '0ms',
|
||||
opacity: '0',
|
||||
scale: '1',
|
||||
x: '0',
|
||||
y: '0',
|
||||
z: '0'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const ucapAnimations = [
|
||||
trigger('animate', [
|
||||
transition('void => *', [useAnimation(customAnimation)])
|
||||
]),
|
||||
|
||||
trigger('animateStagger', [
|
||||
state('50', style('*')),
|
||||
state('100', style('*')),
|
||||
state('200', style('*')),
|
||||
|
||||
transition(
|
||||
'void => 50',
|
||||
query('@*', [stagger('50ms', [animateChild()])], {
|
||||
optional: true
|
||||
})
|
||||
),
|
||||
transition(
|
||||
'void => 100',
|
||||
query('@*', [stagger('100ms', [animateChild()])], {
|
||||
optional: true
|
||||
})
|
||||
),
|
||||
transition(
|
||||
'void => 200',
|
||||
query('@*', [stagger('200ms', [animateChild()])], {
|
||||
optional: true
|
||||
})
|
||||
)
|
||||
]),
|
||||
|
||||
trigger('fadeInOut', [
|
||||
state(
|
||||
'0, void',
|
||||
style({
|
||||
opacity: 0
|
||||
})
|
||||
),
|
||||
state(
|
||||
'1, *',
|
||||
style({
|
||||
opacity: 1
|
||||
})
|
||||
),
|
||||
transition('1 => 0', animate('300ms ease-out')),
|
||||
transition('0 => 1', animate('300ms ease-in')),
|
||||
transition('void <=> *', animate('300ms ease-in'))
|
||||
]),
|
||||
|
||||
trigger('slideInOut', [
|
||||
state(
|
||||
'0',
|
||||
style({
|
||||
height: '0px'
|
||||
})
|
||||
),
|
||||
state(
|
||||
'1',
|
||||
style({
|
||||
height: '*'
|
||||
})
|
||||
),
|
||||
transition('1 => 0', animate('300ms ease-out')),
|
||||
transition('0 => 1', animate('300ms ease-in'))
|
||||
]),
|
||||
|
||||
trigger('slideIn', [
|
||||
transition('void => left', [
|
||||
style({
|
||||
transform: 'translateX(100%)'
|
||||
}),
|
||||
animate(
|
||||
'300ms ease-in',
|
||||
style({
|
||||
transform: 'translateX(0)'
|
||||
})
|
||||
)
|
||||
]),
|
||||
transition('left => void', [
|
||||
style({
|
||||
transform: 'translateX(0)'
|
||||
}),
|
||||
animate(
|
||||
'300ms ease-in',
|
||||
style({
|
||||
transform: 'translateX(-100%)'
|
||||
})
|
||||
)
|
||||
]),
|
||||
transition('void => right', [
|
||||
style({
|
||||
transform: 'translateX(-100%)'
|
||||
}),
|
||||
animate(
|
||||
'300ms ease-in',
|
||||
style({
|
||||
transform: 'translateX(0)'
|
||||
})
|
||||
)
|
||||
]),
|
||||
transition('right => void', [
|
||||
style({
|
||||
transform: 'translateX(0)'
|
||||
}),
|
||||
animate(
|
||||
'300ms ease-in',
|
||||
style({
|
||||
transform: 'translateX(100%)'
|
||||
})
|
||||
)
|
||||
])
|
||||
]),
|
||||
|
||||
trigger('slideInLeft', [
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
transform: 'translateX(-100%)'
|
||||
})
|
||||
),
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
transform: 'translateX(0)'
|
||||
})
|
||||
),
|
||||
transition('void => *', animate('300ms')),
|
||||
transition('* => void', animate('300ms'))
|
||||
]),
|
||||
|
||||
trigger('slideInRight', [
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
transform: 'translateX(100%)'
|
||||
})
|
||||
),
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
transform: 'translateX(0)'
|
||||
})
|
||||
),
|
||||
transition('void => *', animate('300ms')),
|
||||
transition('* => void', animate('300ms'))
|
||||
]),
|
||||
|
||||
trigger('slideInTop', [
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
transform: 'translateY(-100%)'
|
||||
})
|
||||
),
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
transform: 'translateY(0)'
|
||||
})
|
||||
),
|
||||
transition('void => *', animate('300ms')),
|
||||
transition('* => void', animate('300ms'))
|
||||
]),
|
||||
|
||||
trigger('slideInBottom', [
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
transform: 'translateY(100%)'
|
||||
})
|
||||
),
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
transform: 'translateY(0)'
|
||||
})
|
||||
),
|
||||
transition('void => *', animate('300ms')),
|
||||
transition('* => void', animate('300ms'))
|
||||
]),
|
||||
|
||||
trigger('expandCollapse', [
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
height: '0px'
|
||||
})
|
||||
),
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
height: '*'
|
||||
})
|
||||
),
|
||||
transition('void => *', animate('300ms ease-out')),
|
||||
transition('* => void', animate('300ms ease-in'))
|
||||
]),
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Router animations
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
trigger('routerTransitionLeft', [
|
||||
transition('* => *', [
|
||||
query(
|
||||
'content > :enter, content > :leave',
|
||||
[
|
||||
style({
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0
|
||||
})
|
||||
],
|
||||
{ optional: true }
|
||||
),
|
||||
query(
|
||||
'content > :enter',
|
||||
[
|
||||
style({
|
||||
transform: 'translateX(100%)',
|
||||
opacity: 0
|
||||
})
|
||||
],
|
||||
{ optional: true }
|
||||
),
|
||||
sequence([
|
||||
group([
|
||||
query(
|
||||
'content > :leave',
|
||||
[
|
||||
style({
|
||||
transform: 'translateX(0)',
|
||||
opacity: 1
|
||||
}),
|
||||
animate(
|
||||
'600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
|
||||
style({
|
||||
transform: 'translateX(-100%)',
|
||||
opacity: 0
|
||||
})
|
||||
)
|
||||
],
|
||||
{ optional: true }
|
||||
),
|
||||
query(
|
||||
'content > :enter',
|
||||
[
|
||||
style({ transform: 'translateX(100%)' }),
|
||||
animate(
|
||||
'600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
|
||||
style({
|
||||
transform: 'translateX(0%)',
|
||||
opacity: 1
|
||||
})
|
||||
)
|
||||
],
|
||||
{ optional: true }
|
||||
)
|
||||
]),
|
||||
query('content > :leave', animateChild(), { optional: true }),
|
||||
query('content > :enter', animateChild(), { optional: true })
|
||||
])
|
||||
])
|
||||
]),
|
||||
|
||||
trigger('routerTransitionRight', [
|
||||
transition('* => *', [
|
||||
query(
|
||||
'content > :enter, content > :leave',
|
||||
[
|
||||
style({
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0
|
||||
})
|
||||
],
|
||||
{ optional: true }
|
||||
),
|
||||
query(
|
||||
'content > :enter',
|
||||
[
|
||||
style({
|
||||
transform: 'translateX(-100%)',
|
||||
opacity: 0
|
||||
})
|
||||
],
|
||||
{ optional: true }
|
||||
),
|
||||
sequence([
|
||||
group([
|
||||
query(
|
||||
'content > :leave',
|
||||
[
|
||||
style({
|
||||
transform: 'translateX(0)',
|
||||
opacity: 1
|
||||
}),
|
||||
animate(
|
||||
'600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
|
||||
style({
|
||||
transform: 'translateX(100%)',
|
||||
opacity: 0
|
||||
})
|
||||
)
|
||||
],
|
||||
{ optional: true }
|
||||
),
|
||||
query(
|
||||
'content > :enter',
|
||||
[
|
||||
style({ transform: 'translateX(-100%)' }),
|
||||
animate(
|
||||
'600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
|
||||
style({
|
||||
transform: 'translateX(0%)',
|
||||
opacity: 1
|
||||
})
|
||||
)
|
||||
],
|
||||
{ optional: true }
|
||||
)
|
||||
]),
|
||||
query('content > :leave', animateChild(), { optional: true }),
|
||||
query('content > :enter', animateChild(), { optional: true })
|
||||
])
|
||||
])
|
||||
]),
|
||||
|
||||
trigger('routerTransitionUp', [
|
||||
transition('* => *', [
|
||||
query(
|
||||
'content > :enter, content > :leave',
|
||||
[
|
||||
style({
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0
|
||||
})
|
||||
],
|
||||
{ optional: true }
|
||||
),
|
||||
query(
|
||||
'content > :enter',
|
||||
[
|
||||
style({
|
||||
transform: 'translateY(100%)',
|
||||
opacity: 0
|
||||
})
|
||||
],
|
||||
{ optional: true }
|
||||
),
|
||||
group([
|
||||
query(
|
||||
'content > :leave',
|
||||
[
|
||||
style({
|
||||
transform: 'translateY(0)',
|
||||
opacity: 1
|
||||
}),
|
||||
animate(
|
||||
'600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
|
||||
style({
|
||||
transform: 'translateY(-100%)',
|
||||
opacity: 0
|
||||
})
|
||||
)
|
||||
],
|
||||
{ optional: true }
|
||||
),
|
||||
query(
|
||||
'content > :enter',
|
||||
[
|
||||
style({ transform: 'translateY(100%)' }),
|
||||
animate(
|
||||
'600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
|
||||
style({
|
||||
transform: 'translateY(0%)',
|
||||
opacity: 1
|
||||
})
|
||||
)
|
||||
],
|
||||
{ optional: true }
|
||||
)
|
||||
]),
|
||||
query('content > :leave', animateChild(), { optional: true }),
|
||||
query('content > :enter', animateChild(), { optional: true })
|
||||
])
|
||||
]),
|
||||
|
||||
trigger('routerTransitionDown', [
|
||||
transition('* => *', [
|
||||
query(
|
||||
'content > :enter, content > :leave',
|
||||
[
|
||||
style({
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0
|
||||
})
|
||||
],
|
||||
{ optional: true }
|
||||
),
|
||||
query(
|
||||
'content > :enter',
|
||||
[
|
||||
style({
|
||||
transform: 'translateY(-100%)',
|
||||
opacity: 0
|
||||
})
|
||||
],
|
||||
{ optional: true }
|
||||
),
|
||||
sequence([
|
||||
group([
|
||||
query(
|
||||
'content > :leave',
|
||||
[
|
||||
style({
|
||||
transform: 'translateY(0)',
|
||||
opacity: 1
|
||||
}),
|
||||
animate(
|
||||
'600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
|
||||
style({
|
||||
transform: 'translateY(100%)',
|
||||
opacity: 0
|
||||
})
|
||||
)
|
||||
],
|
||||
{ optional: true }
|
||||
),
|
||||
query(
|
||||
'content > :enter',
|
||||
[
|
||||
style({ transform: 'translateY(-100%)' }),
|
||||
animate(
|
||||
'600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
|
||||
style({
|
||||
transform: 'translateY(0%)',
|
||||
opacity: 1
|
||||
})
|
||||
)
|
||||
],
|
||||
{ optional: true }
|
||||
)
|
||||
]),
|
||||
query('content > :leave', animateChild(), { optional: true }),
|
||||
query('content > :enter', animateChild(), { optional: true })
|
||||
])
|
||||
])
|
||||
]),
|
||||
|
||||
trigger('routerTransitionFade', [
|
||||
transition(
|
||||
'* => *',
|
||||
group([
|
||||
query(
|
||||
'content > :enter, content > :leave ',
|
||||
[
|
||||
style({
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0
|
||||
})
|
||||
],
|
||||
{ optional: true }
|
||||
),
|
||||
|
||||
query(
|
||||
'content > :enter',
|
||||
[
|
||||
style({
|
||||
opacity: 0
|
||||
})
|
||||
],
|
||||
{ optional: true }
|
||||
),
|
||||
query(
|
||||
'content > :leave',
|
||||
[
|
||||
style({
|
||||
opacity: 1
|
||||
}),
|
||||
animate(
|
||||
'300ms cubic-bezier(0.0, 0.0, 0.2, 1)',
|
||||
style({
|
||||
opacity: 0
|
||||
})
|
||||
)
|
||||
],
|
||||
{ optional: true }
|
||||
),
|
||||
query(
|
||||
'content > :enter',
|
||||
[
|
||||
style({
|
||||
opacity: 0
|
||||
}),
|
||||
animate(
|
||||
'300ms cubic-bezier(0.0, 0.0, 0.2, 1)',
|
||||
style({
|
||||
opacity: 1
|
||||
})
|
||||
)
|
||||
],
|
||||
{ optional: true }
|
||||
),
|
||||
query('content > :enter', animateChild(), { optional: true }),
|
||||
query('content > :leave', animateChild(), { optional: true })
|
||||
])
|
||||
)
|
||||
]),
|
||||
|
||||
trigger('treeToggler', [
|
||||
state(
|
||||
'0, void',
|
||||
style({
|
||||
opacity: 0
|
||||
})
|
||||
),
|
||||
state(
|
||||
'1, *',
|
||||
style({
|
||||
opacity: 1
|
||||
})
|
||||
),
|
||||
transition('1 => 0', animate('300ms ease-out')),
|
||||
transition('0 => 1', animate('300ms ease-in')),
|
||||
transition('void <=> *', animate('300ms ease-in'))
|
||||
]),
|
||||
|
||||
/**
|
||||
* Floating ACtion Button Animation.
|
||||
*/
|
||||
trigger('fabToggler', [
|
||||
state(
|
||||
'inactive',
|
||||
style({
|
||||
transform: 'rotate(0deg)'
|
||||
})
|
||||
),
|
||||
state(
|
||||
'active',
|
||||
style({
|
||||
transform: 'rotate(225deg)'
|
||||
})
|
||||
),
|
||||
transition('* <=> *', animate('200ms cubic-bezier(0.4, 0.0, 0.2, 1)'))
|
||||
]),
|
||||
trigger('speedDialStagger', [
|
||||
transition('* => *', [
|
||||
query(':enter', style({ opacity: 0 }), { optional: true }),
|
||||
|
||||
query(
|
||||
':enter',
|
||||
stagger('40ms', [
|
||||
animate(
|
||||
'200ms cubic-bezier(0.4, 0.0, 0.2, 1)',
|
||||
keyframes([
|
||||
style({ opacity: 0, transform: 'translateY(10px)' }),
|
||||
style({ opacity: 1, transform: 'translateY(0)' })
|
||||
])
|
||||
)
|
||||
]),
|
||||
{ optional: true }
|
||||
),
|
||||
|
||||
query(
|
||||
':leave',
|
||||
animate(
|
||||
'200ms cubic-bezier(0.4, 0.0, 0.2, 1)',
|
||||
keyframes([style({ opacity: 1 }), style({ opacity: 0 })])
|
||||
),
|
||||
{ optional: true }
|
||||
)
|
||||
])
|
||||
])
|
||||
];
|
198
src/app/pages/organization/component/detail-table.component.html
Normal file
198
src/app/pages/organization/component/detail-table.component.html
Normal file
|
@ -0,0 +1,198 @@
|
|||
<!-- <cdk-virtual-scroll-viewport
|
||||
#dtViewPort
|
||||
perfectScrollbar
|
||||
tvsItemSize="53"
|
||||
headerHeight="56"
|
||||
style="height: 400px;"
|
||||
> -->
|
||||
<div class="">
|
||||
<p>아키텍처솔루션팀 20명</p>
|
||||
<mat-form-field class="example-full-width" appearance="none">
|
||||
<mat-select placeholder="회사">
|
||||
<mat-option
|
||||
*ngFor="let searchItem of searchItemList"
|
||||
[value]="searchItem"
|
||||
>
|
||||
{{ searchItem.itemName }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="example-full-width" appearance="none">
|
||||
<mat-select placeholder="상태">
|
||||
<mat-option
|
||||
*ngFor="let searchItem of searchItemList"
|
||||
[value]="searchItem"
|
||||
>
|
||||
{{ searchItem.itemName }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="example-full-width" appearance="none">
|
||||
<mat-select placeholder="부서">
|
||||
<mat-option
|
||||
*ngFor="let searchItem of searchItemList"
|
||||
[value]="searchItem"
|
||||
>
|
||||
{{ searchItem.itemName }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="example-full-width" appearance="none">
|
||||
<mat-select placeholder="직급(직책)">
|
||||
<mat-option
|
||||
*ngFor="let searchItem of searchItemList"
|
||||
[value]="searchItem"
|
||||
>
|
||||
{{ searchItem.itemName }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div>
|
||||
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8" matSort>
|
||||
<ng-container matColumnDef="profileImage">
|
||||
<th mat-header-cell *matHeaderCellDef class="profileImage">
|
||||
<span class="ui-column-divider"></span>
|
||||
<span>
|
||||
profileImage
|
||||
</span>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let element" class="profileImage">
|
||||
<div class="table-item">
|
||||
<span
|
||||
class="presence"
|
||||
[matTooltip]="true"
|
||||
matTooltipPosition="after"
|
||||
></span>
|
||||
<span class="thumbnail-mask">
|
||||
<img />
|
||||
</span>
|
||||
<span *ngIf="false" class="text-accent-color marker-mobile-state">
|
||||
<mat-icon>phone_android</mat-icon>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="profileInfo">
|
||||
<th mat-header-cell *matHeaderCellDef class="profileInfo" minWidth="150">
|
||||
<span class="ui-column-divider resizable"></span>
|
||||
<span mat-sort-header="name">
|
||||
이름
|
||||
</span>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let element" class="profileInfo">
|
||||
<div class="baseInfo">
|
||||
<span *ngIf="true" class="work-status" [ngClass]="work - status">
|
||||
휴가중
|
||||
</span>
|
||||
<span class="name">
|
||||
이름
|
||||
</span>
|
||||
<span class="grade">
|
||||
직급
|
||||
</span>
|
||||
</div>
|
||||
<div class="deptName">
|
||||
아키텍처솔루션팀
|
||||
</div>
|
||||
|
||||
<div class="workplace">
|
||||
빅데이터,인사정보
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="company_hpNumber">
|
||||
<th mat-header-cell *matHeaderCellDef minWidth="75">
|
||||
<span class="ui-column-divider resizable"></span>
|
||||
<div mat-sort-header="company">
|
||||
연락처
|
||||
</div>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<div class="companyName">
|
||||
LGCNS
|
||||
</div>
|
||||
<div class="hpNumber" (click)="onClickCall('MOBILE', element)">
|
||||
010-3043-2921
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="responsibilities_email">
|
||||
<th mat-header-cell *matHeaderCellDef minWidth="90">
|
||||
<span class="ui-column-divider"></span>
|
||||
<div mat-sort-header="responsibilities">
|
||||
이메일
|
||||
</div>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<div class="responsibilities">
|
||||
dkdk
|
||||
</div>
|
||||
<div class="email">
|
||||
avdkekdl@namver.com
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="checkable">
|
||||
<th mat-header-cell *matHeaderCellDef>
|
||||
<mat-checkbox
|
||||
(change)="$event ? masterToggle() : null"
|
||||
[checked]="selection.hasValue() && isAllSelected()"
|
||||
[indeterminate]="selection.hasValue() && !isAllSelected()"
|
||||
[aria-label]="checkboxLabel()"
|
||||
>
|
||||
</mat-checkbox>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let row">
|
||||
<mat-checkbox
|
||||
(click)="$event.stopPropagation()"
|
||||
(change)="$event ? selection.toggle(row) : null"
|
||||
[checked]="selection.isSelected(row)"
|
||||
[aria-label]="checkboxLabel(row)"
|
||||
>
|
||||
</mat-checkbox>
|
||||
</td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<mat-form-field class="example-chip-list">
|
||||
<mat-chip-list #chipList aria-label="Fruit selection">
|
||||
<mat-chip
|
||||
*ngFor="let fruit of fruits"
|
||||
[selectable]="selectable"
|
||||
[removable]="removable"
|
||||
(removed)="remove(fruit)"
|
||||
>
|
||||
{{ fruit }}
|
||||
<mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
|
||||
</mat-chip>
|
||||
<input
|
||||
placeholder="New fruit..."
|
||||
#fruitInput
|
||||
[formControl]="fruitCtrl"
|
||||
[matAutocomplete]="auto"
|
||||
[matChipInputFor]="chipList"
|
||||
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
|
||||
(matChipInputTokenEnd)="add($event)"
|
||||
/>
|
||||
</mat-chip-list>
|
||||
<mat-autocomplete
|
||||
#auto="matAutocomplete"
|
||||
(optionSelected)="selected($event)"
|
||||
>
|
||||
<mat-option *ngFor="let fruit of filteredFruits | async" [value]="fruit">
|
||||
{{ fruit }}
|
||||
</mat-option>
|
||||
</mat-autocomplete>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<!-- </cdk-virtual-scroll-viewport> -->
|
||||
<!-- <div
|
||||
class="no-search-result"
|
||||
fxFlexFill
|
||||
*ngIf="!sortedData || 0 === sortedData.length"
|
||||
></div> -->
|
235
src/app/pages/organization/component/detail-table.component.scss
Normal file
235
src/app/pages/organization/component/detail-table.component.scss
Normal file
|
@ -0,0 +1,235 @@
|
|||
@charset 'utf-8';
|
||||
@mixin ellipsis($row) {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@if $row == 1 {
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
} @else if $row >= 2 {
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: $row;
|
||||
-webkit-box-orient: vertical;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
}
|
||||
@mixin disable-selection {
|
||||
-webkit-touch-callout: none; /* iOS Safari */
|
||||
-webkit-user-select: none; /* Safari */
|
||||
-khtml-user-select: none; /* Konqueror HTML */
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* Internet Explorer/Edge */
|
||||
user-select: none; /* Non-prefixed version, currently supported by Chrome and Opera */
|
||||
}
|
||||
|
||||
/*.scrollbar {
|
||||
height: 550px;
|
||||
}*/
|
||||
|
||||
.wrapper {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
mat-form-field {
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
}
|
||||
.list-chip {
|
||||
height: 100px;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border: 1px solid #dddddd;
|
||||
overflow: auto;
|
||||
background-color: #f9f9f9;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
min-width: 600px;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
th.mat-header-cell {
|
||||
@include disable-selection;
|
||||
position: relative;
|
||||
padding: 0 10px;
|
||||
|
||||
span.ui-column-divider {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 0;
|
||||
margin: 0;
|
||||
width: 2px;
|
||||
height: 40px;
|
||||
padding: 0;
|
||||
cursor: initial;
|
||||
border: none;
|
||||
background-color: #d4d4d4;
|
||||
|
||||
&.resizable {
|
||||
cursor: col-resize;
|
||||
}
|
||||
}
|
||||
span {
|
||||
&[mat-sort-header='name'],
|
||||
&[mat-sort-header='grade'] {
|
||||
display: inline-flex;
|
||||
padding-right: 10px;
|
||||
}
|
||||
}
|
||||
&.profileImage {
|
||||
width: 90px;
|
||||
}
|
||||
&.mat-column-checkable {
|
||||
width: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
td.mat-cell {
|
||||
padding: 6px;
|
||||
position: relative;
|
||||
|
||||
div {
|
||||
@include ellipsis(1);
|
||||
}
|
||||
div:nth-chlid(2) {
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
&.profileImage {
|
||||
width: 90px;
|
||||
text-overflow: unset;
|
||||
flex: 0 0 90px;
|
||||
|
||||
.table-item {
|
||||
display: flex;
|
||||
width: 70px;
|
||||
min-width: 70px;
|
||||
font-size: 1em;
|
||||
|
||||
.presence {
|
||||
transform: translateY(6px);
|
||||
}
|
||||
.thumbnail {
|
||||
cursor: pointer;
|
||||
&-mask {
|
||||
display: inline-block;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
margin-right: 0;
|
||||
position: relative;
|
||||
img {
|
||||
width: 40px;
|
||||
height: auto;
|
||||
background-color: #efefef;
|
||||
}
|
||||
}
|
||||
}
|
||||
.marker-mobile-state {
|
||||
position: absolute;
|
||||
background-color: #ffffff;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
bottom: 0;
|
||||
left: 64px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
.mat-icon {
|
||||
font-size: 0.9em;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
min-width: 18px;
|
||||
min-height: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.mat-column-checkable {
|
||||
padding-left: 10px;
|
||||
flex: 0 0 50px;
|
||||
}
|
||||
|
||||
&.profileInfo {
|
||||
cursor: pointer;
|
||||
flex: 0 0 200px;
|
||||
.baseInfo {
|
||||
display: flex;
|
||||
font-size: 1em;
|
||||
@include ellipsis(1);
|
||||
.name {
|
||||
font-size: 1em;
|
||||
font-weight: 600;
|
||||
}
|
||||
.grade {
|
||||
font-size: 0.86em;
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
.deptName {
|
||||
font-size: 0.9em;
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
|
||||
.companyName,
|
||||
.workplace,
|
||||
.responsibilities {
|
||||
font-size: 0.86em;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.hpNumber {
|
||||
cursor: pointer;
|
||||
}
|
||||
.lineNumber {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.work-status {
|
||||
display: inline-block;
|
||||
justify-content: center;
|
||||
justify-items: center;
|
||||
color: #ffffff;
|
||||
height: 100%;
|
||||
min-width: 32px;
|
||||
margin-right: 4px;
|
||||
border-radius: 24px;
|
||||
flex: 0 0 auto;
|
||||
font-size: 0.8em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.no-search-result {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
margin-top: 40px;
|
||||
justify-content: center;
|
||||
justify-items: center;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
::ng-deep .integrate-search-org {
|
||||
td.mat-cell {
|
||||
&.profileInfo {
|
||||
cursor: initial !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep .ps__rail-y {
|
||||
z-index: 101;
|
||||
}
|
||||
|
||||
.example-chip-list {
|
||||
width: 100%;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DetailTableComponent } from './detail-table.component';
|
||||
|
||||
describe('Organization::DetailTableComponent', () => {
|
||||
let component: DetailTableComponent;
|
||||
let fixture: ComponentFixture<DetailTableComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [DetailTableComponent]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DetailTableComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
197
src/app/pages/organization/component/detail-table.component.ts
Normal file
197
src/app/pages/organization/component/detail-table.component.ts
Normal file
|
@ -0,0 +1,197 @@
|
|||
import {
|
||||
Component,
|
||||
ViewChild,
|
||||
OnInit,
|
||||
ChangeDetectorRef,
|
||||
ElementRef
|
||||
} from '@angular/core';
|
||||
import { COMMA, ENTER } from '@angular/cdk/keycodes';
|
||||
import { PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
|
||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
import { SelectionModel } from '@angular/cdk/collections';
|
||||
import { MatSort } from '@angular/material/sort';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { Observable } from 'rxjs';
|
||||
import { startWith, map } from 'rxjs/operators';
|
||||
import {
|
||||
MatAutocomplete,
|
||||
MatAutocompleteSelectedEvent
|
||||
} from '@angular/material/autocomplete';
|
||||
import { MatChipInputEvent } from '@angular/material/chips';
|
||||
|
||||
export interface PeriodicElement {
|
||||
name: string;
|
||||
position: number;
|
||||
weight: string;
|
||||
}
|
||||
|
||||
export interface UserInfo {
|
||||
/** 사용자SEQ */
|
||||
seq: number;
|
||||
/** 사용자명 */
|
||||
name: string;
|
||||
}
|
||||
|
||||
const ELEMENT_DATA: PeriodicElement[] = [
|
||||
{ position: 1, name: 'LGCNS', weight: '' },
|
||||
{ position: 2, name: 'LGCNS', weight: '' },
|
||||
{ position: 3, name: 'LGCNS', weight: '' },
|
||||
{ position: 4, name: 'LGCNS', weight: '' },
|
||||
{ position: 5, name: 'LGCNS', weight: '' },
|
||||
{ position: 6, name: 'LGCNS', weight: '' }
|
||||
];
|
||||
|
||||
@Component({
|
||||
selector: 'app-organization-detail-table',
|
||||
templateUrl: './detail-table.component.html',
|
||||
styleUrls: ['./detail-table.component.scss']
|
||||
})
|
||||
export class DetailTableComponent implements OnInit {
|
||||
displayedColumns2: string[] = ['position', 'name', 'weight', 'select'];
|
||||
displayedColumns: string[] = [
|
||||
'profileImage',
|
||||
'profileInfo',
|
||||
'company_hpNumber',
|
||||
'responsibilities_email',
|
||||
'checkable'
|
||||
];
|
||||
|
||||
selectedUserList1: UserInfo[] = [
|
||||
{ seq: 1, name: 'Helium' },
|
||||
{ seq: 2, name: 'Hydrogen' },
|
||||
{ seq: 3, name: 'Lithium' },
|
||||
{ seq: 4, name: 'Beryllium' },
|
||||
{ seq: 5, name: 'Carbon' },
|
||||
{ seq: 6, name: 'Boron' }
|
||||
];
|
||||
|
||||
selectedUserList: UserInfo[] = [
|
||||
{ seq: 1, name: 'Helium' },
|
||||
{ seq: 2, name: 'Hydrogen' },
|
||||
{ seq: 3, name: 'Lithium' },
|
||||
{ seq: 4, name: 'Beryllium' },
|
||||
{ seq: 5, name: 'Carbon' },
|
||||
{ seq: 6, name: 'Boron' }
|
||||
];
|
||||
|
||||
searchItemList: any[] = [{ itemName: '전체' }, { itemName: '부서' }];
|
||||
|
||||
visible = true;
|
||||
selectable = true;
|
||||
removable = true;
|
||||
separatorKeysCodes: number[] = [ENTER, COMMA];
|
||||
fruitCtrl = new FormControl();
|
||||
filteredFruits: Observable<string[]>;
|
||||
fruits: string[] = ['Lemon'];
|
||||
allFruits: string[] = ['Apple', 'Lemon', 'Lime', 'Orange', 'Strawberry'];
|
||||
|
||||
@ViewChild(MatSort)
|
||||
sort: MatSort;
|
||||
|
||||
@ViewChild('fruitInput') fruitInput: ElementRef<HTMLInputElement>;
|
||||
@ViewChild('auto') matAutocomplete: MatAutocomplete;
|
||||
|
||||
dataSource: MatTableDataSource<PeriodicElement>;
|
||||
selection: SelectionModel<PeriodicElement>;
|
||||
|
||||
constructor(private changeDetectorRef: ChangeDetectorRef) {
|
||||
this.dataSource = new MatTableDataSource<PeriodicElement>(ELEMENT_DATA);
|
||||
this.selection = new SelectionModel<PeriodicElement>(true, []);
|
||||
this.filteredFruits = this.fruitCtrl.valueChanges.pipe(
|
||||
startWith(null),
|
||||
map((fruit: string | null) =>
|
||||
fruit ? this._filter(fruit) : this.allFruits.slice()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.dataSource.sort = this.sort;
|
||||
this.dataSource.filterPredicate = (
|
||||
data: PeriodicElement,
|
||||
filterJson: string
|
||||
) => {
|
||||
const matchFilter = [];
|
||||
const filters = JSON.parse(filterJson);
|
||||
|
||||
filters.forEach((filter) => {
|
||||
const val = data[filter.id] === null ? '' : data[filter.id];
|
||||
matchFilter.push(
|
||||
val.toLowerCase().includes(filter.value.toLowerCase())
|
||||
);
|
||||
});
|
||||
return matchFilter.every(Boolean);
|
||||
};
|
||||
}
|
||||
|
||||
/** Whether the number of selected elements matches the total number of rows. */
|
||||
isAllSelected() {
|
||||
const numSelected = this.selection.selected.length;
|
||||
const numRows = this.dataSource.data.length;
|
||||
return numSelected === numRows;
|
||||
}
|
||||
|
||||
/** Selects all rows if they are not all selected; otherwise clear selection. */
|
||||
masterToggle() {
|
||||
this.isAllSelected()
|
||||
? this.selection.clear()
|
||||
: this.dataSource.data.forEach((row) => this.selection.select(row));
|
||||
}
|
||||
|
||||
/** The label for the checkbox on the passed row */
|
||||
checkboxLabel(row?: PeriodicElement): string {
|
||||
if (!row) {
|
||||
return `${this.isAllSelected() ? 'select' : 'deselect'} all`;
|
||||
}
|
||||
return `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${
|
||||
row.position + 1
|
||||
}`;
|
||||
}
|
||||
|
||||
onClickDeleteUser(userInfo: UserInfo) {
|
||||
this.selectedUserList = this.selectedUserList.filter(
|
||||
(item) => item.seq !== userInfo.seq
|
||||
);
|
||||
this.changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
||||
add(event: MatChipInputEvent): void {
|
||||
const input = event.input;
|
||||
const value = event.value;
|
||||
|
||||
// Add our fruit
|
||||
if ((value || '').trim()) {
|
||||
this.fruits.push(value.trim());
|
||||
}
|
||||
|
||||
// Reset the input value
|
||||
if (input) {
|
||||
input.value = '';
|
||||
}
|
||||
|
||||
this.fruitCtrl.setValue(null);
|
||||
}
|
||||
|
||||
remove(fruit: string): void {
|
||||
const index = this.fruits.indexOf(fruit);
|
||||
|
||||
if (index >= 0) {
|
||||
this.fruits.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
selected(event: MatAutocompleteSelectedEvent): void {
|
||||
this.fruits.push(event.option.viewValue);
|
||||
this.fruitInput.nativeElement.value = '';
|
||||
this.fruitCtrl.setValue(null);
|
||||
}
|
||||
|
||||
private _filter(value: string): string[] {
|
||||
const filterValue = value.toLowerCase();
|
||||
|
||||
return this.allFruits.filter(
|
||||
(fruit) => fruit.toLowerCase().indexOf(filterValue) === 0
|
||||
);
|
||||
}
|
||||
}
|
102
src/app/pages/organization/component/tree.component.html
Normal file
102
src/app/pages/organization/component/tree.component.html
Normal file
|
@ -0,0 +1,102 @@
|
|||
<cdk-virtual-scroll-viewport
|
||||
#cvsvOrganization
|
||||
itemSize="36"
|
||||
perfectScrollbar
|
||||
fxFlexFill
|
||||
style="height: 400px;"
|
||||
>
|
||||
<ng-container
|
||||
*cdkVirtualFor="let node of dataSource.expandedData$"
|
||||
></ng-container>
|
||||
<mat-tree
|
||||
fxFlexFill
|
||||
#orgranizationTree
|
||||
[dataSource]="dataSource"
|
||||
[treeControl]="treeControl"
|
||||
class="organization-tree"
|
||||
>
|
||||
<!-- This is the tree node template for leaf nodes -->
|
||||
<mat-tree-node
|
||||
*matTreeNodeDef="let node"
|
||||
matTreeNodePadding
|
||||
matTreeNodePaddingIndent="20"
|
||||
class="tree-no-child"
|
||||
>
|
||||
<div
|
||||
class="tree-node-closer-container"
|
||||
*ngFor="let i of appendDivArray(node.level)"
|
||||
>
|
||||
<div
|
||||
class="tree-node-closer-top"
|
||||
[style.left.px]="20 - 20 * i"
|
||||
[attr.last-node]="isLastNode(node, i) ? '' : null"
|
||||
[attr.sub-node]="0 < i ? '' : null"
|
||||
></div>
|
||||
<div
|
||||
class="tree-node-closer-bottom"
|
||||
[style.left.px]="20 - 20 * i"
|
||||
[attr.last-node]="isLastNode(node, i) ? '' : null"
|
||||
[attr.sub-node]="0 < i ? '' : null"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<li (click)="onClickNode(node)" matRipple>
|
||||
<div class="tree-node-body">
|
||||
<!-- {{ node.deptInfo | ucapTranslate: 'name' }} -->
|
||||
{{ node.deptInfo.name }}
|
||||
</div>
|
||||
</li>
|
||||
</mat-tree-node>
|
||||
<!-- This is the tree node template for expandable nodes -->
|
||||
<mat-tree-node
|
||||
*matTreeNodeDef="let node; when: hasChild"
|
||||
matTreeNodePadding
|
||||
matTreeNodePaddingIndent="20"
|
||||
class="tree-has-child"
|
||||
>
|
||||
<div
|
||||
class="tree-node-closer-container"
|
||||
*ngFor="let i of appendDivArray(node.level)"
|
||||
>
|
||||
<div
|
||||
class="tree-node-closer-top"
|
||||
[style.left.px]="20 - 20 * i"
|
||||
[attr.last-node]="isLastNode(node, i) ? '' : null"
|
||||
[attr.sub-node]="0 < i ? '' : null"
|
||||
></div>
|
||||
<div
|
||||
class="tree-node-closer-bottom"
|
||||
[style.left.px]="20 - 20 * i"
|
||||
[attr.expanded]="treeControl.isExpanded(node) ? '' : null"
|
||||
[attr.last-node]="isLastNode(node, i) ? '' : null"
|
||||
[attr.sub-node]="0 < i ? '' : null"
|
||||
></div>
|
||||
</div>
|
||||
<li (click)="onClickNode(node)" matRipple>
|
||||
<div class="tree-node-body">
|
||||
<span class="horizontal-line"></span>
|
||||
<button
|
||||
mat-icon-button
|
||||
color="accent"
|
||||
matTreeNodeToggle
|
||||
[attr.aria-label]="'toggle ' + node.filename"
|
||||
>
|
||||
<mat-icon
|
||||
class="tree-node-expand-btn"
|
||||
[@romvoeAdd]="treeControl.isExpanded(node) ? 'remove' : 'add'"
|
||||
>
|
||||
{{ treeControl.isExpanded(node) ? 'remove' : 'add' }}
|
||||
</mat-icon>
|
||||
</button>
|
||||
<span class="dept-name">
|
||||
<!-- {{
|
||||
node.deptInfo | ucapTranslate: 'name'
|
||||
}} -->
|
||||
{{ node.deptInfo.name }}
|
||||
</span>
|
||||
</div>
|
||||
<!-- <ul class="tree-node-closer"></ul> -->
|
||||
</li>
|
||||
</mat-tree-node>
|
||||
</mat-tree>
|
||||
</cdk-virtual-scroll-viewport>
|
97
src/app/pages/organization/component/tree.component.scss
Normal file
97
src/app/pages/organization/component/tree.component.scss
Normal file
|
@ -0,0 +1,97 @@
|
|||
.organization-tree {
|
||||
padding: 5px;
|
||||
|
||||
.tree-node-closer-container {
|
||||
position: relative;
|
||||
|
||||
.tree-node-closer-top {
|
||||
width: 15px;
|
||||
height: 40px;
|
||||
position: absolute;
|
||||
border: 1px dotted #cccccc;
|
||||
border-width: 0 0 1px 1px;
|
||||
top: -40px;
|
||||
}
|
||||
.tree-node-closer-bottom {
|
||||
width: 15px;
|
||||
height: 40px;
|
||||
position: absolute;
|
||||
border: 1px dotted #cccccc;
|
||||
border-width: 0 0 1px 1px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
.tree-node-closer-top[sub-node] {
|
||||
border-width: 0 0 0 1px;
|
||||
}
|
||||
.tree-node-closer-top[sub-node][last-node] {
|
||||
border-width: 0 0 0 0;
|
||||
}
|
||||
|
||||
.tree-node-closer-bottom[expanded] {
|
||||
border-width: 0 0 1px 0px;
|
||||
}
|
||||
.tree-node-closer-bottom[last-node] {
|
||||
border-width: 0 0 1px 0px;
|
||||
}
|
||||
.tree-node-closer-bottom[sub-node] {
|
||||
border-width: 0 0 0 1px;
|
||||
}
|
||||
.tree-node-closer-bottom[sub-node][last-node] {
|
||||
border-width: 0 0 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.tree-has-child {
|
||||
height: 36px;
|
||||
min-height: 36px;
|
||||
li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
|
||||
.tree-node-body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
border-radius: 4px;
|
||||
button {
|
||||
line-height: normal;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
.tree-node-expand-btn {
|
||||
background-color: transparent;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tree-no-child {
|
||||
height: 36px;
|
||||
min-height: 36px;
|
||||
font-size: 13px;
|
||||
li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
|
||||
.tree-node-body {
|
||||
padding-left: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
24
src/app/pages/organization/component/tree.component.spec.ts
Normal file
24
src/app/pages/organization/component/tree.component.spec.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TreeComponent } from './tree.component';
|
||||
|
||||
describe('UserItemComponent', () => {
|
||||
let component: TreeComponent;
|
||||
let fixture: ComponentFixture<TreeComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [TreeComponent]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(TreeComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
261
src/app/pages/organization/component/tree.component.ts
Normal file
261
src/app/pages/organization/component/tree.component.ts
Normal file
|
@ -0,0 +1,261 @@
|
|||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
ViewChild,
|
||||
ChangeDetectorRef,
|
||||
AfterViewInit
|
||||
} from '@angular/core';
|
||||
import { trigger, transition, style, animate } from '@angular/animations';
|
||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||
import { FlatTreeControl } from '@angular/cdk/tree';
|
||||
import { VirtualScrollTreeFlatDataSource } from '../datasource/virtual-scroll-tree-flat.data-source';
|
||||
import { MatTreeFlattener, MatTree } from '@angular/material/tree';
|
||||
|
||||
import { ucapAnimations } from './animation';
|
||||
|
||||
export enum DeptType {
|
||||
// R: 기관Root
|
||||
Root = 'R',
|
||||
// D: 본부
|
||||
Department = 'D',
|
||||
// T: 부서
|
||||
Team = 'T'
|
||||
}
|
||||
|
||||
interface DeptInfo {
|
||||
/** 부서SEQ */
|
||||
seq: number;
|
||||
/** 부서명 */
|
||||
name: string;
|
||||
/** 부서타입 */
|
||||
type: DeptType;
|
||||
/** 본부SEQ */
|
||||
rootSeq: number;
|
||||
/** 상위부서SEQ */
|
||||
parentSeq: number;
|
||||
}
|
||||
interface OrganizationNode {
|
||||
deptInfo: DeptInfo;
|
||||
name: string;
|
||||
children?: OrganizationNode[];
|
||||
}
|
||||
|
||||
interface FlatNode {
|
||||
expandable: boolean;
|
||||
name: string;
|
||||
level: number;
|
||||
deptInfo: DeptInfo;
|
||||
}
|
||||
const deptInfoList: DeptInfo[] = [
|
||||
{
|
||||
seq: 1,
|
||||
name: '사장실',
|
||||
type: DeptType.Root,
|
||||
rootSeq: 0,
|
||||
parentSeq: 0
|
||||
},
|
||||
{
|
||||
seq: 2,
|
||||
name: '고문실',
|
||||
type: DeptType.Department,
|
||||
rootSeq: 1,
|
||||
parentSeq: 1
|
||||
},
|
||||
{
|
||||
seq: 3,
|
||||
name: '아키텍처솔루션팀',
|
||||
type: DeptType.Department,
|
||||
rootSeq: 1,
|
||||
parentSeq: 1
|
||||
},
|
||||
{
|
||||
seq: 4,
|
||||
name: '사장님 O/H',
|
||||
type: DeptType.Team,
|
||||
rootSeq: 1,
|
||||
parentSeq: 2
|
||||
},
|
||||
{
|
||||
seq: 5,
|
||||
name: 'DT 사업부',
|
||||
type: DeptType.Department,
|
||||
rootSeq: 1,
|
||||
parentSeq: 3
|
||||
},
|
||||
{
|
||||
seq: 6,
|
||||
name: '클라우드 사업부',
|
||||
type: DeptType.Department,
|
||||
rootSeq: 1,
|
||||
parentSeq: 3
|
||||
},
|
||||
{
|
||||
seq: 7,
|
||||
name: 'LF 팀',
|
||||
type: DeptType.Team,
|
||||
rootSeq: 2,
|
||||
parentSeq: 2
|
||||
}
|
||||
];
|
||||
|
||||
@Component({
|
||||
selector: 'app-tree',
|
||||
templateUrl: './tree.component.html',
|
||||
styleUrls: ['./tree.component.scss'],
|
||||
animations: [
|
||||
ucapAnimations,
|
||||
trigger('romvoeAdd', [
|
||||
transition('remove <=> add', [
|
||||
style({
|
||||
transform: `rotate(45deg)`,
|
||||
opacity: 0
|
||||
}),
|
||||
animate('.2s 0s ease-out')
|
||||
])
|
||||
])
|
||||
]
|
||||
})
|
||||
export class TreeComponent implements OnInit, AfterViewInit {
|
||||
@ViewChild('cvsvOrganization', { static: false })
|
||||
cvsvOrganization: CdkVirtualScrollViewport;
|
||||
treeControl: FlatTreeControl<FlatNode>;
|
||||
treeFlattener: MatTreeFlattener<OrganizationNode, FlatNode>;
|
||||
dataSource: VirtualScrollTreeFlatDataSource<OrganizationNode, FlatNode>;
|
||||
|
||||
constructor() {
|
||||
this.treeControl = new FlatTreeControl<FlatNode>(
|
||||
(node) => node.level,
|
||||
(node) => node.expandable
|
||||
);
|
||||
this.treeFlattener = new MatTreeFlattener<OrganizationNode, FlatNode>(
|
||||
(node: OrganizationNode, level: number) => {
|
||||
return {
|
||||
expandable: !!node.children && node.children.length > 0,
|
||||
name: node.name,
|
||||
level,
|
||||
deptInfo: node.deptInfo
|
||||
};
|
||||
},
|
||||
(node) => node.level,
|
||||
(node) => node.expandable,
|
||||
(node) => node.children
|
||||
);
|
||||
|
||||
this.dataSource = new VirtualScrollTreeFlatDataSource<
|
||||
OrganizationNode,
|
||||
FlatNode
|
||||
>(this.treeControl, this.treeFlattener);
|
||||
|
||||
const nodeMap = new Map<number, OrganizationNode>();
|
||||
const rootNodeList: OrganizationNode[] = [];
|
||||
const remainChildNodeList: OrganizationNode[] = [];
|
||||
|
||||
deptInfoList.forEach((deptInfo) => {
|
||||
const node: OrganizationNode = {
|
||||
deptInfo,
|
||||
name: deptInfo.name,
|
||||
children: []
|
||||
};
|
||||
if (nodeMap.has(deptInfo.seq)) {
|
||||
return;
|
||||
}
|
||||
nodeMap.set(deptInfo.seq, node);
|
||||
|
||||
if (0 === deptInfo.parentSeq) {
|
||||
rootNodeList.push(node);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nodeMap.has(deptInfo.parentSeq)) {
|
||||
nodeMap.get(deptInfo.parentSeq).children.push(node);
|
||||
} else {
|
||||
remainChildNodeList.push(node);
|
||||
}
|
||||
});
|
||||
|
||||
remainChildNodeList.forEach((node) => {
|
||||
if (nodeMap.has(node.deptInfo.parentSeq)) {
|
||||
nodeMap.get(node.deptInfo.parentSeq).children.push(node);
|
||||
}
|
||||
});
|
||||
this.dataSource.data = rootNodeList;
|
||||
}
|
||||
|
||||
ngOnInit(): void {}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.dataSource.cdkVirtualScrollViewport = this.cvsvOrganization;
|
||||
|
||||
this.cvsvOrganization.scrollToOffset(100);
|
||||
}
|
||||
|
||||
hasChild = (_: number, node: FlatNode) => node.expandable;
|
||||
|
||||
onClickNode(node: OrganizationNode) {
|
||||
// this.selected.emit(node.deptInfo);
|
||||
console.log(node);
|
||||
}
|
||||
|
||||
isLastNode(node: FlatNode, depth: number): boolean {
|
||||
const i = this.findNodeIndex(node, depth);
|
||||
|
||||
if (-1 === i) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (i === this.dataSource.expandedDataSubject.value.length - 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const n = this.dataSource.expandedDataSubject.value[i];
|
||||
|
||||
for (
|
||||
let idx = i + 1;
|
||||
idx < this.dataSource.expandedDataSubject.value.length;
|
||||
idx++
|
||||
) {
|
||||
const element = this.dataSource.expandedDataSubject.value[idx];
|
||||
if (n.level === element.level) {
|
||||
return false;
|
||||
}
|
||||
if (n.level > element.level) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
appendDivArray(level: number): number[] {
|
||||
if (0 === level) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Array.from({ length: level }, (_, i: number) => i);
|
||||
}
|
||||
|
||||
private findNodeIndex(node: FlatNode, depth: number): number {
|
||||
if (!node) {
|
||||
return -1;
|
||||
}
|
||||
const i = this.dataSource.expandedDataSubject.value.findIndex((n) => {
|
||||
return node.deptInfo.seq === n.deptInfo.seq;
|
||||
});
|
||||
|
||||
if (0 === depth) {
|
||||
return i;
|
||||
}
|
||||
return this.findNodeIndex(this.findParentNode(i), depth - 1);
|
||||
}
|
||||
|
||||
private findParentNode(index: number): FlatNode {
|
||||
const node = this.dataSource.expandedDataSubject.value[index];
|
||||
|
||||
for (let idx = index - 1; idx >= 0; idx--) {
|
||||
const n = this.dataSource.expandedDataSubject.value[idx];
|
||||
if (n.level === node.level - 1) {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
import { CollectionViewer, DataSource } from '@angular/cdk/collections';
|
||||
import { FlatTreeControl } from '@angular/cdk/tree';
|
||||
import {
|
||||
BehaviorSubject,
|
||||
merge,
|
||||
Observable,
|
||||
Subject,
|
||||
Subscription
|
||||
} from 'rxjs';
|
||||
import { map, share } from 'rxjs/operators';
|
||||
import { MatTreeFlattener } from '@angular/material/tree';
|
||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||
|
||||
export class VirtualScrollTreeFlatDataSource<T, F> extends DataSource<F> {
|
||||
private flattenedDataSubject = new BehaviorSubject<F[]>([]);
|
||||
|
||||
expandedDataSubject = new BehaviorSubject<F[]>([]);
|
||||
expandedData$: Observable<F[]>;
|
||||
|
||||
private connectSubject: Subject<F[]>;
|
||||
private dataChangeSubscription: Subscription;
|
||||
private rangeChangeSubscription: Subscription;
|
||||
|
||||
private rangeSubject: BehaviorSubject<{
|
||||
start: number;
|
||||
end: number;
|
||||
}>;
|
||||
|
||||
// tslint:disable-next-line: variable-name
|
||||
private _cdkVirtualScrollViewport: CdkVirtualScrollViewport;
|
||||
set cdkVirtualScrollViewport(
|
||||
cdkVirtualScrollViewport: CdkVirtualScrollViewport
|
||||
) {
|
||||
if (!cdkVirtualScrollViewport) {
|
||||
return;
|
||||
}
|
||||
this._cdkVirtualScrollViewport = cdkVirtualScrollViewport;
|
||||
this.rangeSubject = new BehaviorSubject<{ start: number; end: number }>({
|
||||
start: 0,
|
||||
end: 1
|
||||
});
|
||||
|
||||
this.rangeChangeSubscription = cdkVirtualScrollViewport.renderedRangeStream.subscribe(
|
||||
(range) => {
|
||||
this.rangeSubject.next({
|
||||
start: range.start,
|
||||
end: range.end
|
||||
});
|
||||
if (!!this.connectSubject) {
|
||||
this.connectSubject.next(
|
||||
this.expandedDataSubject.value.slice(
|
||||
this.rangeSubject.value.start,
|
||||
this.rangeSubject.value.end
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// tslint:disable-next-line: variable-name
|
||||
private _data: BehaviorSubject<T[]>;
|
||||
get data() {
|
||||
return this._data.value;
|
||||
}
|
||||
set data(value: T[]) {
|
||||
this._data.next(value);
|
||||
this.flattenedDataSubject.next(this.treeFlattener.flattenNodes(this.data));
|
||||
this.treeControl.dataNodes = this.flattenedDataSubject.value;
|
||||
}
|
||||
|
||||
constructor(
|
||||
private treeControl: FlatTreeControl<F>,
|
||||
private treeFlattener: MatTreeFlattener<T, F>,
|
||||
initialData: T[] = []
|
||||
) {
|
||||
super();
|
||||
this._data = new BehaviorSubject<T[]>(initialData);
|
||||
this.expandedData$ = this.expandedDataSubject.asObservable().pipe(share());
|
||||
}
|
||||
|
||||
connect(collectionViewer: CollectionViewer): Observable<F[]> {
|
||||
this.connectSubject = new Subject<F[]>();
|
||||
|
||||
this.dataChangeSubscription = merge(
|
||||
collectionViewer.viewChange,
|
||||
this.treeControl.expansionModel.changed,
|
||||
this.flattenedDataSubject
|
||||
)
|
||||
.pipe(
|
||||
map(() => {
|
||||
this.expandedDataSubject.next(
|
||||
this.treeFlattener.expandFlattenedNodes(
|
||||
this.flattenedDataSubject.value,
|
||||
this.treeControl
|
||||
)
|
||||
);
|
||||
|
||||
return !this.rangeSubject
|
||||
? this.expandedDataSubject.value
|
||||
: this.expandedDataSubject.value.slice(
|
||||
this.rangeSubject.value.start,
|
||||
this.rangeSubject.value.end
|
||||
);
|
||||
})
|
||||
)
|
||||
.subscribe((datas) => {
|
||||
this.connectSubject.next(datas);
|
||||
if (!!this._cdkVirtualScrollViewport) {
|
||||
this._cdkVirtualScrollViewport.checkViewportSize();
|
||||
}
|
||||
});
|
||||
|
||||
return this.connectSubject.asObservable();
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
if (!!this.connectSubject) {
|
||||
this.connectSubject.next();
|
||||
this.connectSubject.unsubscribe();
|
||||
}
|
||||
|
||||
if (!!this.dataChangeSubscription) {
|
||||
this.dataChangeSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
if (!!this.rangeChangeSubscription) {
|
||||
this.rangeChangeSubscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
}
|
298
src/app/pages/organization/organization.component.html
Normal file
298
src/app/pages/organization/organization.component.html
Normal file
|
@ -0,0 +1,298 @@
|
|||
<div class="container">
|
||||
<div class="gnb">
|
||||
<mat-toolbar>logo</mat-toolbar>
|
||||
<mat-tab-group
|
||||
mat-stretch-tabs
|
||||
animationDuration="0ms"
|
||||
backgroundColor="transparent"
|
||||
class="global-menu"
|
||||
[selectedIndex]="2"
|
||||
>
|
||||
<mat-tab aria-label="Group">
|
||||
<ng-template mat-tab-label>
|
||||
<div class="icon-item" matTooltip="그룹" matTooltipPosition="after">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
|
||||
<circle cx="12" cy="7" r="4"></circle>
|
||||
</svg>
|
||||
</div>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
<mat-tab aria-label="Chat">
|
||||
<ng-template mat-tab-label>
|
||||
<div
|
||||
class="icon-item"
|
||||
matBadgeHidden="false"
|
||||
matBadge="275"
|
||||
matBadgeColor="accent"
|
||||
matBadgePosition="above after"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="#000000"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="bevel"
|
||||
>
|
||||
<path
|
||||
d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
<mat-tab aria-label="Organization">
|
||||
<ng-template mat-tab-label>
|
||||
<div class="icon-item">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="#000000"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="bevel"
|
||||
>
|
||||
<circle class="st0" cx="18.4" cy="18.5" r="3" />
|
||||
<circle class="st0" cx="12" cy="5" r="3" />
|
||||
<path class="st0" d="M12.4,10.5h4c1.1,0,2,0.9,2,2v3" />
|
||||
<circle class="st0" cx="6.1" cy="18.5" r="3" />
|
||||
<path class="st0" d="M6.1,15.5v-3c0-1.1,0.9-2,2-2h4" />
|
||||
<line class="st0" x1="12" y1="8" x2="12" y2="9" />
|
||||
</svg>
|
||||
</div>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
|
||||
<mat-tab aria-label="Message">
|
||||
<ng-template mat-tab-label>
|
||||
<div class="icon-item">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="#000000"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="bevel"
|
||||
>
|
||||
<polygon
|
||||
points="21.368 12.001 3 21.609 3 14 11 12 3 9.794 3 2.394"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</div>
|
||||
|
||||
<div class="menu-container">
|
||||
<div class="contents">
|
||||
<mat-drawer-container class="example-container" style="height: 600px;">
|
||||
<mat-drawer #rightSideDrawer mode="side" opened style="width: 400px;">
|
||||
<mat-toolbar>
|
||||
<div>Organization</div>
|
||||
<div></div>
|
||||
</mat-toolbar>
|
||||
<div class="list-section">
|
||||
<div class="title-section">
|
||||
<div class="title">
|
||||
<h3>조직도</h3>
|
||||
<div class="btn-box">
|
||||
<button
|
||||
mat-icon-button
|
||||
[matMenuTriggerFor]="menu"
|
||||
aria-label="group menu"
|
||||
>
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list"><app-tree></app-tree></div>
|
||||
</div>
|
||||
</mat-drawer>
|
||||
<!-- (click)="onClickToggle($event)" -->
|
||||
<mat-drawer-content style="width: 500px;">
|
||||
<mat-toolbar>
|
||||
<div><span>Today</span>2020.05.05</div>
|
||||
<div>
|
||||
<div class="app-layout-native-title-bar-actions">
|
||||
<button
|
||||
mat-icon-button
|
||||
class="button app-layout-native-title-bar-minimize"
|
||||
>
|
||||
<!--<mat-icon>minimize</mat-icon>-->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<line x1="5" y1="18" x2="19" y2="18"></line>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
mat-icon-button
|
||||
class="button app-layout-native-title-bar-maximize"
|
||||
>
|
||||
<ng-container [ngSwitch]="'Maximized'">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="round"
|
||||
*ngSwitchCase="'Maximized'"
|
||||
>
|
||||
<path
|
||||
class="st0"
|
||||
d="M15,9.5v7c0,0.8-0.7,1.5-1.5,1.5h-7C5.7,18,5,17.3,5,16.5v-7C5,8.7,5.7,8,6.5,8h7C14.3,8,15,8.7,15,9.5z"
|
||||
/>
|
||||
<path
|
||||
class="st0"
|
||||
d="M8.8,6.8V6c0-0.8,0.7-1.5,1.5-1.5H17c0.8,0,1.5,0.7,1.5,1.5v6.8c0,0.8-0.7,1.5-1.5,1.5h-0.8"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<!--<mat-icon *ngSwitchDefault>crop_din</mat-icon>-->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="round"
|
||||
*ngSwitchDefault
|
||||
>
|
||||
<rect
|
||||
x="5"
|
||||
y="5"
|
||||
width="12"
|
||||
height="12"
|
||||
rx="2"
|
||||
ry="2"
|
||||
></rect>
|
||||
</svg>
|
||||
</ng-container>
|
||||
</button>
|
||||
<button
|
||||
mat-icon-button
|
||||
class="button app-layout-native-title-bar-close"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</mat-toolbar>
|
||||
<div class="contents-main">
|
||||
<!-- search start-->
|
||||
<div fxLayout="column" fxFlex="1 1 auto" class="ingegrated-search">
|
||||
<div class="org-search-container">
|
||||
<mat-form-field class="example-full-width" appearance="none">
|
||||
<mat-select placeholder="전체">
|
||||
<mat-option
|
||||
*ngFor="let searchItem of searchItemList"
|
||||
[value]="searchItem"
|
||||
>
|
||||
{{ searchItem.itemName }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<input matInput placeholder="검색어를 입력하세요." />
|
||||
<button
|
||||
mat-icon-button
|
||||
*ngIf="true"
|
||||
class="icon-button font-accent-color"
|
||||
aria-label="Clear"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||||
</svg>
|
||||
<!-- <mat-icon>close</mat-icon> -->
|
||||
<!-- <i class="mdi mdi-close">X</i> -->
|
||||
</button>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<!-- search end-->
|
||||
<!-- content table start-->
|
||||
<app-organization-detail-table></app-organization-detail-table>
|
||||
<!-- content table end-->
|
||||
contents area
|
||||
</div>
|
||||
</mat-drawer-content>
|
||||
</mat-drawer-container>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<div>
|
||||
<span>현재버전 0.0.11</span>
|
||||
<span>최신버전 0.0.11</span>
|
||||
</div>
|
||||
<div style="right: 0;">
|
||||
HelpDesk 1661-9066
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-menu #menu="matMenu">
|
||||
<button mat-menu-item>Item 1</button>
|
||||
<button mat-menu-item>Item 2</button>
|
||||
</mat-menu>
|
110
src/app/pages/organization/organization.component.scss
Normal file
110
src/app/pages/organization/organization.component.scss
Normal file
|
@ -0,0 +1,110 @@
|
|||
.container {
|
||||
.gnb,
|
||||
.menu-container {
|
||||
float: left;
|
||||
|
||||
.list-section {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// .contents {
|
||||
// .list-section,
|
||||
// .contents-main {
|
||||
// float: left;
|
||||
// }
|
||||
// }
|
||||
|
||||
.footer {
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
.gnb {
|
||||
.left-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.global-menu {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep .global-menu {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
.mat-tab-header {
|
||||
border-bottom: none !important;
|
||||
width: 100%;
|
||||
}
|
||||
.mat-tab-label-container {
|
||||
.mat-tab-list {
|
||||
.mat-tab-labels {
|
||||
flex-flow: column;
|
||||
height: 360px;
|
||||
padding-top: 10px;
|
||||
border-bottom: none;
|
||||
|
||||
.mat-tab-label {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
padding: 0;
|
||||
min-width: 0 !important;
|
||||
.mat-tab-label-content {
|
||||
.icon-item {
|
||||
display: inline-flex;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
transform: scale(0.9);
|
||||
transition: transform 0.3s cubic-bezier(0.4, 0, 0, 1);
|
||||
|
||||
svg {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
stroke: #ffffff;
|
||||
stroke-width: 1.5;
|
||||
stroke-linecap: square;
|
||||
stroke-linejoin: miter;
|
||||
fill: none;
|
||||
}
|
||||
.mat-badge-content {
|
||||
right: -4px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.mat-tab-label-active {
|
||||
opacity: 0;
|
||||
}
|
||||
&[aria-selected='true'] {
|
||||
opacity: 1;
|
||||
.mat-tab-label-content {
|
||||
.icon-item {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.mat-ink-bar {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.mat-tab-body-wrapper {
|
||||
.mat-tab-body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
div {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
25
src/app/pages/organization/organization.component.spec.ts
Normal file
25
src/app/pages/organization/organization.component.spec.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { OrganizationComponent } from './organization.component';
|
||||
|
||||
describe('OrganizationComponent', () => {
|
||||
let component: OrganizationComponent;
|
||||
let fixture: ComponentFixture<OrganizationComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ OrganizationComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(OrganizationComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
36
src/app/pages/organization/organization.component.stories.ts
Normal file
36
src/app/pages/organization/organization.component.stories.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
import { action } from '@storybook/addon-actions';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { ScrollingModule } from '@angular/cdk/scrolling';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
|
||||
import { moduleMetadata } from '@storybook/angular';
|
||||
import { OrganizationComponent } from './organization.component';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import { TreeComponent } from './component/tree.component';
|
||||
import { DetailTableComponent } from './component/detail-table.component';
|
||||
import { UserItemComponent } from '../../pages/group/component/user-item.component';
|
||||
|
||||
export default {
|
||||
title: 'OrganizationComponent',
|
||||
component: OrganizationComponent,
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
imports: [
|
||||
CommonModule,
|
||||
BrowserModule,
|
||||
ReactiveFormsModule,
|
||||
ScrollingModule,
|
||||
BrowserAnimationsModule,
|
||||
MaterialModule
|
||||
],
|
||||
providers: [],
|
||||
declarations: [TreeComponent, DetailTableComponent, UserItemComponent]
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
export const Page = () => ({
|
||||
component: OrganizationComponent
|
||||
});
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user