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-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 title> |
|||
{{ 'comments.title' | sqxTranslate }} |
|||
</ng-container> |
|||
|
|||
<ng-container content> |
|||
<ng-container *ngIf="mentionUsers | async; let users"> |
|||
|
|||
<div class="comments-list" #commentsList> |
|||
<div (sqxResized)="scrollDown()"> |
|||
<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 *ngFor="let comment of commentsState.comments | async; trackBy: trackByComment" |
|||
[comment]="comment" |
|||
[commentsState]="commentsState" |
|||
[mentionUsers]="users" |
|||
[canEdit]="true" |
|||
[canFollow]="false" |
|||
[userToken]="userToken"> |
|||
</sqx-comment> |
|||
</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"> |
|||
<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> |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
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