media is added

This commit is contained in:
병준 박 2019-08-19 18:41:48 +09:00
parent 61480e2370
commit 434e2da296
14 changed files with 834 additions and 0 deletions

View File

@ -84,6 +84,7 @@ $typography: mat-typography-config(
@import 'src/app/pages/accounts/component/signin.theme'; @import 'src/app/pages/accounts/component/signin.theme';
@import 'src/app/pages/medias/media/medias-media.theme';
@import 'src/app/pages/users/user/user.theme'; @import 'src/app/pages/users/user/user.theme';
// Define a mixin for easier access // Define a mixin for easier access
@ -94,6 +95,7 @@ $typography: mat-typography-config(
@include signin-theme($theme); @include signin-theme($theme);
@include medias-media-theme($theme);
@include users-user-theme($theme); @include users-user-theme($theme);
} }

View File

@ -0,0 +1,207 @@
<div id="media" class="page-layout carded fullwidth inner-scroll">
<!-- TOP BACKGROUND -->
<div class="top-bg accent"></div>
<!-- / TOP BACKGROUND -->
<!-- CENTER -->
<div class="center">
<!-- HEADER -->
<div
class="header accent"
fxLayout="row"
fxLayoutAlign="space-between center"
>
<!-- APP TITLE -->
<div fxLayout="row" fxLayoutAlign="start center">
<button
mat-icon-button
class="mr-0 mr-sm-16"
[routerLink]="'/media/medias'"
>
<mat-icon>arrow_back</mat-icon>
</button>
<!-- <div class="product-image mr-8 mr-sm-16" [@animate]="{value:'*',params:{delay:'50ms',scale:'0.2'}}">
<img *ngIf="product.images[0]" [src]="product.images[0].url">
<img *ngIf="!product.images[0]" [src]="'assets/images/ecommerce/product-image-placeholder.png'">
</div> -->
<div
fxLayout="column"
fxLayoutAlign="start start"
[@animate]="{ value: '*', params: { delay: '100ms', x: '-25px' } }"
>
<div class="h2" *ngIf="pageType === 'edit'">
{{ media.name }}
</div>
<div class="h2" *ngIf="pageType === 'new'">
New Media
</div>
<div class="subtitle secondary-text">
<span>Media Detail</span>
</div>
</div>
</div>
<!-- / APP TITLE -->
<button
mat-raised-button
class="save-media-button"
[disabled]="mediaForm.invalid"
*ngIf="pageType === 'new'"
>
<span>ADD</span>
</button>
<button
mat-raised-button
class="save-media-button"
[disabled]="mediaForm.invalid || mediaForm.pristine"
*ngIf="pageType === 'edit'"
>
<span>SAVE</span>
</button>
</div>
<!-- / HEADER -->
<!-- CONTENT CARD -->
<div class="content-card">
<!-- CONTENT -->
<div class="content">
<form
name="mediaForm"
[formGroup]="mediaForm"
class="media w-100-p"
fxLayout="column"
fxFlex
>
<mat-tab-group>
<mat-tab label="Basic Info">
<div class="tab-content p-24" fusePerfectScrollbar>
<mat-form-field
appearance="outline"
floatLabel="always"
class="w-100-p"
>
<mat-label>Media Name</mat-label>
<input
matInput
placeholder="Media Name"
name="name"
formControlName="name"
required
/>
</mat-form-field>
<mat-form-field
appearance="outline"
floatLabel="always"
class="w-100-p"
>
<mat-label>Media Description</mat-label>
<textarea
matInput
placeholder="Media Description"
name="description"
formControlName="description"
rows="5"
>
</textarea>
</mat-form-field>
<mat-form-field
appearance="outline"
floatLabel="always"
class="w-100-p"
>
<mat-label>Categories</mat-label>
<mat-chip-list
#categoryList
name="categories"
formControlName="categories"
>
<!-- <mat-chip *ngFor="let category of product.categories"
[removable]="true" (removed)="product.removeCategory(category)">
{{category}}
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip> -->
<input
[matChipInputFor]="categoryList"
[matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="product.addCategory($event)"
/>
</mat-chip-list>
</mat-form-field>
<mat-form-field
appearance="outline"
floatLabel="always"
class="w-100-p"
>
<mat-label>Tags</mat-label>
<mat-chip-list #tagList name="tags" formControlName="tags">
<!-- <mat-chip
*ngFor="let tag of product.tags"
[removable]="true"
(removed)="product.removeTag(tag)"
>
{{ tag }}
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip> -->
<input
[matChipInputFor]="tagList"
[matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="product.addTag($event)"
/>
</mat-chip-list>
</mat-form-field>
</div>
</mat-tab>
<mat-tab label="Product Images">
<div class="tab-content p-24" fusePerfectScrollbar>
<!-- <div fxLayout="row wrap" fxLayoutAlign="start start">
<div
*ngIf="product.images.length === 0"
class="product-image"
fxlayout="row"
fxLayoutAlign="center center"
>
<img
class="media"
[src]="
'assets/images/ecommerce/product-image-placeholder.png'
"
/>
</div>
<div *ngFor="let image of product.images">
<div
*ngIf="product.images.length > 0"
class="product-image"
fxlayout="row"
fxLayoutAlign="center center"
>
<img class="media" [src]="image.url" />
</div>
</div>
</div> -->
</div>
</mat-tab>
<mat-tab label="Pricing">
<div class="tab-content p-24" fusePerfectScrollbar></div>
</mat-tab>
</mat-tab-group>
</form>
</div>
<!-- / CONTENT -->
</div>
<!-- / CONTENT CARD -->
</div>
<!-- / CENTER -->
</div>

View File

@ -0,0 +1,62 @@
#media {
.header {
.media-image {
overflow: hidden;
width: 56px;
min-width: 56px;
max-width: 56px;
height: 56px;
min-height: 56px;
max-height: 56px;
border-radius: 4px;
img {
height: 100%;
width: auto;
max-width: none;
}
}
.subtitle {
margin: 6px 0 0 0;
}
}
.content {
.mat-tab-group,
.mat-tab-body-wrapper,
.tab-content {
flex: 1 1 auto;
max-width: 100%;
}
.mat-tab-body-content {
display: flex;
}
.mat-tab-label {
height: 64px;
}
.media-image {
overflow: hidden;
width: 128px;
height: 128px;
margin-right: 16px;
margin-bottom: 16px;
border-radius: 4px;
img {
height: 100%;
width: auto;
max-width: none;
}
}
// Temporary prefix alignment fix
.mat-form-field-appearance-outline .mat-form-field-prefix,
.mat-form-field-appearance-outline .mat-form-field-suffix {
top: 0;
}
}
}

View File

@ -0,0 +1,61 @@
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Location } from '@angular/common';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from 'src/@fuse/animations';
import { FuseUtils } from 'src/@fuse/utils';
@Component({
selector: 'app-pages-medias-media-detail',
templateUrl: './detail.component.html',
styleUrls: ['./detail.component.scss'],
encapsulation: ViewEncapsulation.None,
animations: fuseAnimations
})
export class DetailComponent implements OnInit, OnDestroy {
media: any;
pageType: string;
mediaForm: FormGroup;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*/
constructor(
private _formBuilder: FormBuilder,
private _location: Location,
private _matSnackBar: MatSnackBar
) {
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void {
// Subscribe to update product on changes
}
/**
* On destroy
*/
ngOnDestroy(): void {
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
}

View File

@ -0,0 +1,4 @@
import { DetailComponent } from './detail.component';
import { ListComponent } from './list.component';
export const COMPONENTS = [DetailComponent, ListComponent];

View File

@ -0,0 +1,192 @@
<div id="medias" class="page-layout carded fullwidth inner-scroll">
<!-- TOP BACKGROUND -->
<div class="top-bg accent"></div>
<!-- / TOP BACKGROUND -->
<!-- CENTER -->
<div class="center">
<!-- HEADER -->
<div
class="header accent"
fxLayout="column"
fxLayoutAlign="center center"
fxLayout.gt-sm="row"
fxLayoutAlign.gt-sm="space-between center"
>
<!-- APP TITLE -->
<div
class="logo mb-24 mb-md-0"
fxLayout="row"
fxLayoutAlign="start center"
>
<mat-icon
class="logo-icon s-32 mr-16"
[@animate]="{ value: '*', params: { delay: '50ms', scale: '0.2' } }"
>
music_video
</mat-icon>
<span
class="logo-text h1"
[@animate]="{ value: '*', params: { delay: '100ms', x: '-25px' } }"
>
Medias
</span>
</div>
<!-- / APP TITLE -->
<!-- SEARCH -->
<div class="search-wrapper mx-32 mx-md-0">
<div class="search" fxFlex fxLayout="row" fxLayoutAlign="start center">
<mat-icon>search</mat-icon>
<input #filter placeholder="Search for a media" />
</div>
</div>
<!-- / SEARCH -->
<!-- ADD BUTTON -->
<button
mat-raised-button
[routerLink]="'/media/medias/0'"
class="add-media-button fuse-white mt-24 mt-md-0"
>
<span>ADD NEW MEDIA</span>
</button>
<!-- / ADD BUTTON -->
</div>
<!-- / HEADER -->
<!-- CONTENT CARD -->
<div class="content-card">
<mat-table
class="medias-table"
#table
[dataSource]="dataSource"
matSort
[@animateStagger]="{ value: '50' }"
fusePerfectScrollbar
>
<!-- ID Column -->
<ng-container matColumnDef="id">
<mat-header-cell *matHeaderCellDef mat-sort-header
>ID</mat-header-cell
>
<mat-cell *matCellDef="let media">
<p class="text-truncate">{{ media.id }}</p>
</mat-cell>
</ng-container>
<!-- Image Column -->
<ng-container matColumnDef="image">
<mat-header-cell *matHeaderCellDef></mat-header-cell>
<mat-cell *matCellDef="let media">
<img
class="media-image"
*ngIf="media.featuredImageId"
[alt]="media.name"
[src]="media.images[media.featuredImageId].url"
/>
<img
*ngIf="!media.featuredImageId"
[src]="'assets/images/ecommerce/product-image-placeholder.png'"
/>
</mat-cell>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef mat-sort-header
>Name</mat-header-cell
>
<mat-cell *matCellDef="let media">
<p class="text-truncate">{{ media.name }}</p>
</mat-cell>
</ng-container>
<!-- Category Column -->
<ng-container matColumnDef="category">
<mat-header-cell *matHeaderCellDef fxHide mat-sort-header fxShow.gt-md
>Category</mat-header-cell
>
<mat-cell *matCellDef="let media" fxHide fxShow.gt-md>
<p class="category text-truncate">
{{ media.categories[0] }}
</p>
</mat-cell>
</ng-container>
<!-- Price Column -->
<ng-container matColumnDef="price">
<mat-header-cell *matHeaderCellDef mat-sort-header fxHide fxShow.gt-xs
>Price</mat-header-cell
>
<mat-cell *matCellDef="let media" fxHide fxShow.gt-xs>
<p class="price text-truncate">
{{ media.priceTaxIncl | currency: 'USD':'symbol' }}
</p>
</mat-cell>
</ng-container>
<!-- Quantity Column -->
<ng-container matColumnDef="quantity">
<mat-header-cell *matHeaderCellDef mat-sort-header fxHide fxShow.gt-sm
>Quantity</mat-header-cell
>
<mat-cell *matCellDef="let media" fxHide fxShow.gt-sm>
<span
class="quantity-indicator text-truncate"
[ngClass]="{
'red-500': media.quantity <= 5,
'amber-500': media.quantity > 5 && media.quantity <= 25,
'green-600': media.quantity > 25
}"
>
</span>
<span>
{{ media.quantity }}
</span>
</mat-cell>
</ng-container>
<!-- Active Column -->
<ng-container matColumnDef="active">
<mat-header-cell *matHeaderCellDef mat-sort-header fxHide fxShow.gt-xs
>Active</mat-header-cell
>
<mat-cell *matCellDef="let media" fxHide fxShow.gt-xs>
<mat-icon *ngIf="media.active" class="active-icon green-600 s-16"
>check</mat-icon
>
<mat-icon *ngIf="!media.active" class="active-icon red-500 s-16"
>close</mat-icon
>
</mat-cell>
</ng-container>
<mat-header-row
*matHeaderRowDef="displayedColumns; sticky: true"
></mat-header-row>
<mat-row
*matRowDef="let media; columns: displayedColumns"
class="media"
matRipple
[routerLink]="
'/apps/e-commerce/products/' + media.id + '/' + media.handle
"
>
</mat-row>
</mat-table>
<mat-paginator
#paginator
[length]="10"
[pageIndex]="0"
[pageSize]="20"
[pageSizeOptions]="[5, 10, 20, 50, 100]"
>
</mat-paginator>
</div>
<!-- / CONTENT CARD -->
</div>
<!-- / CENTER -->
</div>

View File

@ -0,0 +1,122 @@
@import 'src/@fuse/scss/fuse';
app-pages-medias-media-list {
#medias {
.top-bg {
@include media-breakpoint('lt-md') {
height: 256px;
}
}
> .center {
> .header {
.search-wrapper {
width: 100%;
max-width: 480px;
border-radius: 28px;
overflow: hidden;
@include mat-elevation(1);
@include media-breakpoint('xs') {
width: 100%;
}
.search {
width: 100%;
height: 48px;
line-height: 48px;
padding: 0 18px;
input {
width: 100%;
height: 48px;
min-height: 48px;
max-height: 48px;
padding: 0 16px;
border: none;
outline: none;
}
}
}
@include media-breakpoint('lt-md') {
padding: 8px 0;
height: 192px !important;
min-height: 192px !important;
max-height: 192px !important;
}
}
}
}
.medias-table {
flex: 1 1 auto;
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
overflow: auto;
-webkit-overflow-scrolling: touch;
.mat-header-row {
min-height: 64px;
}
.media {
position: relative;
cursor: pointer;
height: 84px;
}
.mat-cell {
min-width: 0;
display: flex;
align-items: center;
}
.mat-column-id {
flex: 0 1 84px;
}
.mat-column-image {
flex: 0 1 84px;
.product-image {
width: 52px;
height: 52px;
border: 1px solid rgba(0, 0, 0, 0.12);
}
}
.mat-column-category {
flex: 0 1 240px;
}
.mat-column-price {
flex: 0 1 160px;
}
.mat-column-quantity {
flex: 0 1 160px;
}
.mat-column-active {
flex: 0 1 80px;
}
.quantity-indicator {
display: inline-block;
vertical-align: middle;
width: 8px;
height: 8px;
border-radius: 4px;
margin-right: 8px;
& + span {
display: inline-block;
vertical-align: middle;
}
}
.active-icon {
border-radius: 50%;
}
}
}

View File

@ -0,0 +1,61 @@
import {
Component,
ElementRef,
OnInit,
ViewChild,
ViewEncapsulation
} from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { DataSource } from '@angular/cdk/collections';
import { BehaviorSubject, fromEvent, merge, Observable, Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators';
import { fuseAnimations } from 'src/@fuse/animations';
import { FuseUtils } from 'src/@fuse/utils';
@Component({
selector: 'app-pages-medias-media-list',
templateUrl: './list.component.html',
styleUrls: ['./list.component.scss'],
animations: fuseAnimations,
encapsulation: ViewEncapsulation.None
})
export class ListComponent implements OnInit {
dataSource: any | null;
displayedColumns = [
'id',
'image',
'name',
'category',
'price',
'quantity',
'active'
];
@ViewChild(MatPaginator, { static: true })
paginator: MatPaginator;
@ViewChild(MatSort, { static: true })
sort: MatSort;
@ViewChild('filter', { static: true })
filter: ElementRef;
// Private
private _unsubscribeAll: Subject<any>;
constructor() {
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void {}
}

View File

@ -0,0 +1,21 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { ListComponent } from './component/list.component';
import { DetailComponent } from './component/detail.component';
const routes: Routes = [
{
path: '',
component: ListComponent
},
{
path: ':id',
component: DetailComponent
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class MediasMediaRoutingModule {}

View File

@ -0,0 +1,50 @@
import { NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatChipsModule } from '@angular/material/chips';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatMenuModule } from '@angular/material/menu';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatSelectModule } from '@angular/material/select';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import { MatTabsModule } from '@angular/material/tabs';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { FuseSharedModule } from 'src/@fuse/shared.module';
import { FuseWidgetModule } from 'src/@fuse/components/widget/widget.module';
import { MediasMediaRoutingModule } from './medias-media-routing.module';
import { COMPONENTS } from './component';
@NgModule({
imports: [
MatButtonModule,
MatChipsModule,
MatExpansionModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
MatMenuModule,
MatPaginatorModule,
MatSelectModule,
MatSnackBarModule,
MatSortModule,
MatTableModule,
MatTabsModule,
MatCheckboxModule,
FuseSharedModule,
FuseWidgetModule,
MediasMediaRoutingModule
],
declarations: [...COMPONENTS],
providers: []
})
export class MediasMediaModule {}

View File

@ -0,0 +1,23 @@
@mixin medias-media-theme($theme) {
$background: map-get($theme, background);
$foreground: map-get($theme, foreground);
app-pages-medias-media-list {
.header {
.search-wrapper {
background: map-get($background, card);
.search {
.mat-icon {
color: map-get($foreground, icon);
}
input {
background: map-get($background, card);
color: map-get($foreground, text);
}
}
}
}
}
}

View File

@ -0,0 +1,15 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
const routes: Routes = [
{
path: 'medias',
loadChildren: './media/medias-media.module#MediasMediaModule'
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class MediasRoutingModule {}

View File

@ -0,0 +1,10 @@
import { NgModule } from '@angular/core';
import { MediasRoutingModule } from './medias-routing.module';
@NgModule({
imports: [MediasRoutingModule],
declarations: [],
providers: []
})
export class MediasModule {}

View File

@ -10,6 +10,10 @@ const routes: Routes = [
path: 'dashboard', path: 'dashboard',
loadChildren: './dashboard/dashboard.module#DashboardModule' loadChildren: './dashboard/dashboard.module#DashboardModule'
}, },
{
path: 'media',
loadChildren: './medias/medias.module#MediasModule'
},
{ {
path: 'user', path: 'user',
loadChildren: './users/users.module#UsersModule' loadChildren: './users/users.module#UsersModule'