mirror of https://github.com/Squidex/squidex.git
committed by
GitHub
45 changed files with 1058 additions and 455 deletions
@ -1,28 +0,0 @@ |
|||||
<!DOCTYPE html> |
|
||||
<html> |
|
||||
|
|
||||
<head> |
|
||||
<meta charset="utf-8"> |
|
||||
|
|
||||
<!-- Load the editor sdk from the local folder or https://cloud.squidex.io/scripts/editor-sdk.js --> |
|
||||
<script src="editor-sdk.js"></script> |
|
||||
</head> |
|
||||
|
|
||||
<body> |
|
||||
<textarea style="width: 100%; box-sizing: border-box; height: 100px;" name="content" id="editor"></textarea> |
|
||||
|
|
||||
<script> |
|
||||
var element = document.getElementById('editor'); |
|
||||
|
|
||||
// When the field is instantiated it notified the UI that it has been loaded. |
|
||||
var field = new SquidexFormField(); |
|
||||
|
|
||||
field.onInit(function (context) { |
|
||||
if (context) { |
|
||||
element.innerHTML = JSON.stringify(context, null, 2); |
|
||||
} |
|
||||
}); |
|
||||
</script> |
|
||||
</body> |
|
||||
|
|
||||
</html> |
|
||||
@ -0,0 +1,47 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="utf-8"> |
||||
|
|
||||
|
<!-- Load the editor sdk from the local folder or https://cloud.squidex.io/scripts/editor-sdk.js --> |
||||
|
<script src="editor-sdk.js"></script> |
||||
|
|
||||
|
<style> |
||||
|
textarea { |
||||
|
box-sizing: border-box; |
||||
|
resize: none; |
||||
|
overflow: hidden; |
||||
|
width: 100%; |
||||
|
} |
||||
|
</style> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
<script> |
||||
|
function grow(element) { |
||||
|
element.style.height = "5px"; |
||||
|
element.style.height = (element.scrollHeight)+"px"; |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<textarea oninput="grow(this)" name="content" id="editor"></textarea> |
||||
|
|
||||
|
<script> |
||||
|
var element = document.getElementById('editor'); |
||||
|
|
||||
|
// When the field is instantiated it notifies the UI that it has been loaded. |
||||
|
// |
||||
|
// Furthermore it sends the current size to the parent. |
||||
|
var field = new SquidexFormField(); |
||||
|
|
||||
|
// Init is called once with a context that contains the app name, schema name and authentication information. |
||||
|
field.onInit(function (context) { |
||||
|
element.innerHTML = JSON.stringify(context, null, 2); |
||||
|
|
||||
|
grow(element); |
||||
|
}); |
||||
|
</script> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
||||
@ -0,0 +1,49 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="utf-8"> |
||||
|
|
||||
|
<!-- Load the editor sdk from the local folder or https://cloud.squidex.io/scripts/editor-sdk.js --> |
||||
|
<script src="editor-sdk.js"></script> |
||||
|
|
||||
|
<style> |
||||
|
textarea { |
||||
|
box-sizing: border-box; |
||||
|
border: 0; |
||||
|
border-radius: 0; |
||||
|
resize: none; |
||||
|
overflow: hidden; |
||||
|
width: 100%; |
||||
|
} |
||||
|
</style> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
<script> |
||||
|
function grow(element) { |
||||
|
element.style.height = "5px"; |
||||
|
element.style.height = (element.scrollHeight)+"px"; |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<textarea oninput="grow(this)" name="content" id="editor"></textarea> |
||||
|
|
||||
|
<script> |
||||
|
var element = document.getElementById('editor'); |
||||
|
|
||||
|
// When the field is instantiated it notifies the UI that it has been loaded. |
||||
|
// |
||||
|
// Furthermore it sends the current size to the parent. |
||||
|
var plugin = new SquidexPlugin(); |
||||
|
|
||||
|
// Init is called once with a context that contains the app name, schema name and authentication information. |
||||
|
plugin.onInit(function (context) { |
||||
|
element.innerHTML = JSON.stringify(context, null, 2); |
||||
|
|
||||
|
grow(element); |
||||
|
}); |
||||
|
</script> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
||||
@ -0,0 +1,118 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="utf-8"> |
||||
|
|
||||
|
<!-- Load the editor sdk from the local folder or https://cloud.squidex.io/scripts/editor-sdk.js --> |
||||
|
<script src="editor-sdk.js"></script> |
||||
|
|
||||
|
<script src="https://cdn.jsdelivr.net/npm/algoliasearch@4.0.0/dist/algoliasearch-lite.umd.js" integrity="sha256-MfeKq2Aw9VAkaE9Caes2NOxQf6vUa8Av0JqcUXUGkd0=" crossorigin="anonymous"></script> |
||||
|
<script src="https://cdn.jsdelivr.net/npm/instantsearch.js@4.0.0/dist/instantsearch.production.min.js" integrity="sha256-6S7q0JJs/Kx4kb/fv0oMjS855QTz5Rc2hh9AkIUjUsk=" crossorigin="anonymous"></script> |
||||
|
|
||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/instantsearch.css@7.3.1/themes/algolia-min.css" integrity="sha256-HB49n/BZjuqiCtQQf49OdZn63XuKFaxcIHWf0HNKte8=" crossorigin="anonymous"> |
||||
|
|
||||
|
<style> |
||||
|
.container { |
||||
|
min-height: 400px; |
||||
|
} |
||||
|
|
||||
|
.ais-Hits { |
||||
|
margin-top: 1rem; |
||||
|
} |
||||
|
|
||||
|
.ais-Hits-item { |
||||
|
margin-right: 0; |
||||
|
margin-top: 5px; |
||||
|
width: 100%; |
||||
|
} |
||||
|
|
||||
|
.button-click { |
||||
|
margin-top: 5px; |
||||
|
color: #3389ff; |
||||
|
cursor: pointer; |
||||
|
display: inline-block; |
||||
|
} |
||||
|
|
||||
|
.button-click:hover { |
||||
|
text-decoration: underline; |
||||
|
} |
||||
|
</style> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
<script> |
||||
|
function grow(element) { |
||||
|
element.style.height = "5px"; |
||||
|
element.style.height = (element.scrollHeight)+"px"; |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<div class="container"> |
||||
|
<div id="searchbox"></div> |
||||
|
|
||||
|
<div id="hits"></div> |
||||
|
</div> |
||||
|
|
||||
|
<script> |
||||
|
var element = document.getElementById('editor'); |
||||
|
|
||||
|
// When the field is instantiated it notifies the UI that it has been loaded. |
||||
|
// |
||||
|
// Furthermore it sends the current size to the parent. |
||||
|
var plugin = new SquidexPlugin(); |
||||
|
|
||||
|
// Init is called once with a context that contains the app name, schema name and authentication information. |
||||
|
plugin.onInit(function (context) { |
||||
|
var searchClient = algoliasearch('CFNTEE51PJ', 'afa3a7605277b85348c6fa160fb5cecc'); |
||||
|
|
||||
|
var search = instantsearch({ indexName: 'test', searchClient }); |
||||
|
|
||||
|
document.addEventListener('click', event => { |
||||
|
if (event.target.matches('.button-click')) { |
||||
|
var id = event.target.getAttribute('data-object-id'); |
||||
|
|
||||
|
// We cannot directly navigate to in the iframe because it would only change the URL of the iframe. |
||||
|
plugin.navigate(`/app/${context.appName}/content/${context.schemaName}`); |
||||
|
// plugin.navigate(`/app/${context.appName}/content/${context.schemaName}/${id}`); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
search.addWidgets([ |
||||
|
instantsearch.widgets.searchBox({ |
||||
|
container: '#searchbox', |
||||
|
}), |
||||
|
|
||||
|
instantsearch.widgets.hits({ |
||||
|
container: '#hits', |
||||
|
templates: { |
||||
|
item(hit, bindEvent) { |
||||
|
return ` |
||||
|
<div> |
||||
|
<div class="hit-name"> |
||||
|
${instantsearch.highlight({ |
||||
|
attribute: 'firstname', |
||||
|
hit, |
||||
|
})} |
||||
|
${instantsearch.highlight({ |
||||
|
attribute: 'lastname', |
||||
|
hit, |
||||
|
})} |
||||
|
|
||||
|
<div> |
||||
|
<a data-object-id="${hit.objectID}" class="button-click">EDIT</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
`; |
||||
|
} |
||||
|
}, |
||||
|
}) |
||||
|
]); |
||||
|
|
||||
|
search.start(); |
||||
|
}); |
||||
|
</script> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
||||
@ -1 +1,9 @@ |
|||||
<sqx-comments [commentsId]="commentsId | async"></sqx-comments> |
<sqx-panel desiredWidth="20rem" isBlank="true" [isLazyLoaded]="false" grid="true"> |
||||
|
<ng-container title> |
||||
|
{{ 'comments.title' | sqxTranslate }} |
||||
|
</ng-container> |
||||
|
|
||||
|
<ng-container content> |
||||
|
<sqx-comments [commentsId]="commentsId | async"></sqx-comments> |
||||
|
</ng-container> |
||||
|
</sqx-panel> |
||||
@ -0,0 +1,15 @@ |
|||||
|
<sqx-panel desiredWidth="20rem" isBlank="true" [isLazyLoaded]="false"> |
||||
|
<ng-container title> |
||||
|
{{ 'common.sidebar' | sqxTranslate }} |
||||
|
</ng-container> |
||||
|
|
||||
|
<ng-container content> |
||||
|
<div> |
||||
|
<iframe #iframe scrolling="no" width="100%"></iframe> |
||||
|
</div> |
||||
|
</ng-container> |
||||
|
</sqx-panel> |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
@ -0,0 +1,5 @@ |
|||||
|
iframe { |
||||
|
background: 0; |
||||
|
border: 0; |
||||
|
overflow: hidden; |
||||
|
} |
||||
@ -0,0 +1,113 @@ |
|||||
|
/* |
||||
|
* Squidex Headless CMS |
||||
|
* |
||||
|
* @license |
||||
|
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
||||
|
*/ |
||||
|
|
||||
|
import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, Renderer2, ViewChild } from '@angular/core'; |
||||
|
import { Router } from '@angular/router'; |
||||
|
import { ApiUrlConfig, ResourceOwner, Types } from '@app/framework/internal'; |
||||
|
import { AppsState, AuthService, ContentsState, SchemasState } from '@app/shared'; |
||||
|
import { combineLatest } from 'rxjs'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'sqx-sidebar-page', |
||||
|
styleUrls: ['./sidebar-page.component.scss'], |
||||
|
templateUrl: './sidebar-page.component.html', |
||||
|
changeDetection: ChangeDetectionStrategy.OnPush |
||||
|
}) |
||||
|
export class SidebarPageComponent extends ResourceOwner implements AfterViewInit { |
||||
|
private isInitialized = false; |
||||
|
private context: any; |
||||
|
private content: any; |
||||
|
|
||||
|
@ViewChild('iframe', { static: false }) |
||||
|
public iframe: ElementRef<HTMLIFrameElement>; |
||||
|
|
||||
|
constructor(apiUrl: ApiUrlConfig, authService: AuthService, appsState: AppsState, |
||||
|
private readonly contentsState: ContentsState, |
||||
|
private readonly schemasState: SchemasState, |
||||
|
private readonly renderer: Renderer2, |
||||
|
private readonly router: Router |
||||
|
) { |
||||
|
super(); |
||||
|
|
||||
|
this.context = { |
||||
|
apiUrl: apiUrl.buildUrl('api'), |
||||
|
appId: appsState.snapshot.selectedApp!.id, |
||||
|
appName: appsState.snapshot.selectedApp!.name, |
||||
|
user: authService.user |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
public ngAfterViewInit() { |
||||
|
this.own( |
||||
|
combineLatest([ |
||||
|
this.schemasState.selectedSchema, |
||||
|
this.contentsState.selectedContent |
||||
|
]).subscribe(([schema, content]) => { |
||||
|
const url = |
||||
|
content ? |
||||
|
schema.properties.contentSidebarUrl : |
||||
|
schema.properties.contentsSidebarUrl; |
||||
|
|
||||
|
this.context['schemaName'] = schema.name; |
||||
|
this.context['schemaId'] = schema.id; |
||||
|
|
||||
|
this.iframe.nativeElement.src = url || ''; |
||||
|
})); |
||||
|
|
||||
|
this.own( |
||||
|
this.contentsState.selectedContent |
||||
|
.subscribe(content => { |
||||
|
this.content = content; |
||||
|
|
||||
|
this.sendContent(); |
||||
|
})); |
||||
|
|
||||
|
this.own( |
||||
|
this.renderer.listen('window', 'message', (event: MessageEvent) => { |
||||
|
if (event.source === this.iframe.nativeElement.contentWindow) { |
||||
|
const { type } = event.data; |
||||
|
|
||||
|
if (type === 'started') { |
||||
|
this.isInitialized = true; |
||||
|
|
||||
|
this.sendInit(); |
||||
|
this.sendContent(); |
||||
|
} else if (type === 'resize') { |
||||
|
const { height } = event.data; |
||||
|
|
||||
|
this.iframe.nativeElement.height = height + 'px'; |
||||
|
} else if (type === 'navigate') { |
||||
|
const { url } = event.data; |
||||
|
|
||||
|
this.router.navigateByUrl(url); |
||||
|
} |
||||
|
} |
||||
|
})); |
||||
|
} |
||||
|
|
||||
|
private sendInit() { |
||||
|
this.sendMessage('init', { context: this.context }); |
||||
|
} |
||||
|
|
||||
|
private sendContent() { |
||||
|
this.sendMessage('contentChanged', { content: this.content }); |
||||
|
} |
||||
|
|
||||
|
private sendMessage(type: string, payload: any) { |
||||
|
if (!this.iframe) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
const iframe = this.iframe.nativeElement; |
||||
|
|
||||
|
if (this.isInitialized && iframe.contentWindow && Types.isFunction(iframe.contentWindow.postMessage)) { |
||||
|
const message = { type, ...payload }; |
||||
|
|
||||
|
iframe.contentWindow.postMessage(message, '*'); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,27 +1,28 @@ |
|||||
<sqx-panel desiredWidth="20rem" isBlank="true" [isLazyLoaded]="false" grid="true"> |
<ng-container *ngIf="mentionUsers | async; let users"> |
||||
<ng-container title> |
<div class="comments-list" #commentsList> |
||||
{{ 'comments.title' | sqxTranslate }} |
<div (sqxResized)="scrollDown()"> |
||||
</ng-container> |
<sqx-comment *ngFor="let comment of commentsState.comments | async; trackBy: trackByComment" |
||||
|
[comment]="comment" |
||||
<ng-container content> |
[commentsState]="commentsState" |
||||
<ng-container *ngIf="mentionUsers | async; let users"> |
[mentionUsers]="users" |
||||
|
[canEdit]="true" |
||||
<div class="comments-list" #commentsList> |
[canFollow]="false" |
||||
<div (sqxResized)="scrollDown()"> |
[userToken]="userToken"> |
||||
<sqx-comment *ngFor="let comment of commentsState.comments | async; trackBy: trackByComment" [comment]="comment" [commentsState]="commentsState" [mentionUsers]="users" [canEdit]="true" [canFollow]="false" [userToken]="userToken"> |
</sqx-comment> |
||||
</sqx-comment> |
</div> |
||||
</div> |
</div> |
||||
</div> |
|
||||
|
|
||||
<div class="comments-footer"> |
|
||||
<form [formGroup]="commentForm.form" (ngSubmit)="comment()"> |
|
||||
<input class="form-control" name="text" formControlName="text" placeholder="{{ 'comments.create' | sqxTranslate }}" [mention]="users" [mentionConfig]="mentionConfig" autocomplete="off" autocorrect="off" autocapitalize="off"> |
|
||||
</form> |
|
||||
</div> |
|
||||
</ng-container> |
|
||||
</ng-container> |
|
||||
</sqx-panel> |
|
||||
|
|
||||
|
<div class="comments-footer"> |
||||
|
<form [formGroup]="commentForm.form" (ngSubmit)="comment()"> |
||||
|
<input class="form-control" name="text" formControlName="text" placeholder="{{ 'comments.create' | sqxTranslate }}" |
||||
|
[mention]="users" |
||||
|
[mentionConfig]="mentionConfig" |
||||
|
autocomplete="off" |
||||
|
autocorrect="off" |
||||
|
autocapitalize="off"> |
||||
|
</form> |
||||
|
</div> |
||||
|
</ng-container> |
||||
|
|
||||
|
|
||||
|
|
||||
|
|||||
File diff suppressed because it is too large
Binary file not shown.
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 103 KiB |
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue