uhh, lots of things in frontend
This commit is contained in:
parent
76e8b183ca
commit
2d58312aa0
17 changed files with 30294 additions and 27939 deletions
14
frontend-reactive/app/components/note.hbs
Normal file
14
frontend-reactive/app/components/note.hbs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<div class="note">
|
||||||
|
{{!-- TODO: figure out how to make the entire note clickable for opening with something like {{on "click" (fn this.openFullView)}} --}}
|
||||||
|
<Note::UserHeader
|
||||||
|
@displayname="{{@displayname}}"
|
||||||
|
@handle="@{{@username}}@{{@serverdomain}}"
|
||||||
|
/>
|
||||||
|
<Note::Content @content="{{@content}}" />
|
||||||
|
<div class="note-timestamps-container">
|
||||||
|
<p class="note-timestamp" id="note-edited-timestamp">Edited: At some time in
|
||||||
|
the future</p>
|
||||||
|
<p class="note-timestamp" id="note-created-timestamp">Posted: Before the Big
|
||||||
|
Bang</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
26
frontend-reactive/app/components/note.ts
Normal file
26
frontend-reactive/app/components/note.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import { action } from '@ember/object';
|
||||||
|
import Component from '@glimmer/component';
|
||||||
|
|
||||||
|
export interface NoteSignature {
|
||||||
|
// The arguments accepted by the component
|
||||||
|
Args: {
|
||||||
|
isInTimeline: boolean;
|
||||||
|
};
|
||||||
|
// Any blocks yielded by the component
|
||||||
|
Blocks: {
|
||||||
|
default: [];
|
||||||
|
};
|
||||||
|
// The element to which `...attributes` is applied in the component template
|
||||||
|
Element: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Note extends Component<NoteSignature> {
|
||||||
|
@action
|
||||||
|
openFullView() {
|
||||||
|
if (this.args.isInTimeline) {
|
||||||
|
alert("Would have opened note's own view");
|
||||||
|
} else {
|
||||||
|
console.log("Alread in note specific view, can't open it again");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
frontend-reactive/app/components/note/content.hbs
Normal file
19
frontend-reactive/app/components/note/content.hbs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<div class="note-content">
|
||||||
|
<p class="note-content-text">{{this.visibleContent}}</p>
|
||||||
|
{{#if this.canExpand}}
|
||||||
|
{{#if this.collapsed}}
|
||||||
|
<div
|
||||||
|
type="button"
|
||||||
|
class="note-content-toggle"
|
||||||
|
{{on "click" this.expand}}
|
||||||
|
>Expand</div>
|
||||||
|
{{else}}
|
||||||
|
<div
|
||||||
|
type="button"
|
||||||
|
class="note-content-toggle"
|
||||||
|
{{on "click" this.collapse}}
|
||||||
|
>Collapse</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
57
frontend-reactive/app/components/note/content.ts
Normal file
57
frontend-reactive/app/components/note/content.ts
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import { action } from '@ember/object';
|
||||||
|
import Component from '@glimmer/component';
|
||||||
|
import { tracked } from '@glimmer/tracking';
|
||||||
|
|
||||||
|
export interface NoteContentSignature {
|
||||||
|
// The arguments accepted by the component
|
||||||
|
Args: {
|
||||||
|
content: string;
|
||||||
|
};
|
||||||
|
// Any blocks yielded by the component
|
||||||
|
Blocks: {
|
||||||
|
default: [];
|
||||||
|
};
|
||||||
|
// The element to which `...attributes` is applied in the component template
|
||||||
|
Element: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class NoteContent extends Component<NoteContentSignature> {
|
||||||
|
// Default to collapsed content
|
||||||
|
@tracked visibleContent =
|
||||||
|
this.args.content.length > 200 ? this.cutDownContent() : this.args.content;
|
||||||
|
|
||||||
|
@tracked collapsed = true;
|
||||||
|
@tracked canExpand = this.args.content.length > 200;
|
||||||
|
|
||||||
|
@action
|
||||||
|
expand() {
|
||||||
|
this.visibleContent = this.args.content;
|
||||||
|
this.collapsed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
collapse() {
|
||||||
|
this.visibleContent =
|
||||||
|
this.args.content.length > 200
|
||||||
|
? this.cutDownContent()
|
||||||
|
: this.args.content;
|
||||||
|
this.collapsed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
cutDownContent(): string {
|
||||||
|
if (this.args.content.length > 200) {
|
||||||
|
const words = this.args.content.split(' ');
|
||||||
|
let outString = '';
|
||||||
|
for (const word of words) {
|
||||||
|
if (outString.length > 200) {
|
||||||
|
return outString + '...';
|
||||||
|
}
|
||||||
|
outString += word + ' ';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return this.args.content;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
9
frontend-reactive/app/components/note/user-header.hbs
Normal file
9
frontend-reactive/app/components/note/user-header.hbs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<div class="note-user-header">
|
||||||
|
<div class="note-user-pfp">
|
||||||
|
<p>Pfp</p>
|
||||||
|
</div>
|
||||||
|
<div class="note-user-name-and-handle">
|
||||||
|
<p class="note-user-displayname">{{@displayname}}</p>
|
||||||
|
<p class="note-user-handle">{{@handle}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
0
frontend-reactive/app/components/timeline/.gitkeep
Normal file
0
frontend-reactive/app/components/timeline/.gitkeep
Normal file
|
@ -1,4 +0,0 @@
|
||||||
<div class="timeline-note">
|
|
||||||
<h3>{{@username}}</h3>
|
|
||||||
<p>{{@content}}</p>
|
|
||||||
</div>
|
|
|
@ -1,6 +1,17 @@
|
||||||
/* Ember supports plain CSS out of the box. More info: https://cli.emberjs.com/release/advanced-use/stylesheets/ */
|
/* Ember supports plain CSS out of the box. More info: https://cli.emberjs.com/release/advanced-use/stylesheets/ */
|
||||||
|
@import url("notes.css");
|
||||||
|
|
||||||
.timeline-note {
|
* {
|
||||||
display: flex;
|
font-family:
|
||||||
flex-direction: column;
|
system-ui,
|
||||||
|
-apple-system,
|
||||||
|
BlinkMacSystemFont,
|
||||||
|
"Segoe UI",
|
||||||
|
Roboto,
|
||||||
|
Oxygen,
|
||||||
|
Ubuntu,
|
||||||
|
Cantarell,
|
||||||
|
"Open Sans",
|
||||||
|
"Helvetica Neue",
|
||||||
|
sans-serif;
|
||||||
}
|
}
|
||||||
|
|
87
frontend-reactive/app/styles/notes.css
Normal file
87
frontend-reactive/app/styles/notes.css
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
.note {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: fit-content;
|
||||||
|
height: fit-content;
|
||||||
|
|
||||||
|
/* align-items: center; */
|
||||||
|
border: 1px dashed green;
|
||||||
|
max-width: 50em;
|
||||||
|
padding: 0.5em;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-user-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border: 2px solid black;
|
||||||
|
width: fit-content;
|
||||||
|
padding-right: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-user-pfp {
|
||||||
|
border: 1px dashed red;
|
||||||
|
width: 3em;
|
||||||
|
height: 3em;
|
||||||
|
padding-bottom: 0.1em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-user-name-and-handle {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
/* align-items: center; */
|
||||||
|
padding: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-user-displayname {
|
||||||
|
padding-top: 0.1em;
|
||||||
|
margin: 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-user-handle {
|
||||||
|
font-size: 85%;
|
||||||
|
color: #555;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-timestamps-container {
|
||||||
|
padding-top: 0.2em;
|
||||||
|
padding-bottom: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-timestamp {
|
||||||
|
font-size: 0.8em;
|
||||||
|
margin: -0.1em;
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: fit-content;
|
||||||
|
align-items: center;
|
||||||
|
border: 1px dashed red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-content-text {
|
||||||
|
border: 1px dashed red;
|
||||||
|
margin-top: -0.08em;
|
||||||
|
margin-bottom: -0.08em;
|
||||||
|
padding: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-content-toggle {
|
||||||
|
margin-top: 0.3em;
|
||||||
|
margin-bottom: 0.3em;
|
||||||
|
cursor: default;
|
||||||
|
background-color: #ccc;
|
||||||
|
padding: 0.1em 0.3em 0.2em;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-content-toggle:hover {
|
||||||
|
background-color: #aaa;
|
||||||
|
}
|
|
@ -1,4 +1,14 @@
|
||||||
{{page-title "FrontendReactive"}}
|
{{page-title "FrontendReactive"}}
|
||||||
|
|
||||||
{{outlet}}
|
{{outlet}}
|
||||||
<Timeline::Note @username="bob" @content="Hello world" />
|
<Note
|
||||||
|
@displayname="bob"
|
||||||
|
@username="alice"
|
||||||
|
@serverdomain="example.com"
|
||||||
|
@isInTimeline="false"
|
||||||
|
@content="Scuttle crack Jennys tea cup American Main lass Jolly Roger prow reef sails tackle ye Chain Shot. Cackle fruit topgallant draft bilge gangplank Jolly Roger ahoy holystone black jack aye. Mizzenmast stern warp Buccaneer Spanish Main Letter of Marque pink aft skysail grog blossom.
|
||||||
|
|
||||||
|
Crow's nest scuppers topgallant fore dance the hempen jig loot tack fluke squiffy flogging. Red ensign Letter of Marque poop deck scallywag chandler rutters sheet avast sloop to go on account. Spike loaded to the gunwalls prow smartly gabion heave down scallywag interloper chantey case shot.
|
||||||
|
|
||||||
|
Quarterdeck cackle fruit ballast lookout bounty jack trysail crow's nest hulk spyglass. Gabion gangplank long boat coffer ahoy wench parley American Main jack come about. Trysail code of conduct cable provost loaded to the gunwalls chase landlubber or just lubber gibbet gunwalls hempen halter."
|
||||||
|
/>
|
|
@ -5,6 +5,9 @@ const EmberApp = require('ember-cli/lib/broccoli/ember-app');
|
||||||
module.exports = function (defaults) {
|
module.exports = function (defaults) {
|
||||||
const app = new EmberApp(defaults, {
|
const app = new EmberApp(defaults, {
|
||||||
'ember-cli-babel': { enableTypeScriptTransform: true },
|
'ember-cli-babel': { enableTypeScriptTransform: true },
|
||||||
|
minifyCSS: {
|
||||||
|
options: { processImport: true },
|
||||||
|
},
|
||||||
|
|
||||||
// Add options here
|
// Add options here
|
||||||
});
|
});
|
||||||
|
|
57888
frontend-reactive/package-lock.json
generated
57888
frontend-reactive/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -36,11 +36,6 @@
|
||||||
"@glint/template": "^1.4.0",
|
"@glint/template": "^1.4.0",
|
||||||
"@tsconfig/ember": "^3.0.8",
|
"@tsconfig/ember": "^3.0.8",
|
||||||
"@types/ember": "^4.0.11",
|
"@types/ember": "^4.0.11",
|
||||||
"@types/ember-data": "^4.4.16",
|
|
||||||
"@types/ember-data__adapter": "^4.0.6",
|
|
||||||
"@types/ember-data__model": "^4.0.5",
|
|
||||||
"@types/ember-data__serializer": "^4.0.6",
|
|
||||||
"@types/ember-data__store": "^4.0.7",
|
|
||||||
"@types/ember__application": "^4.0.11",
|
"@types/ember__application": "^4.0.11",
|
||||||
"@types/ember__array": "^4.0.10",
|
"@types/ember__array": "^4.0.10",
|
||||||
"@types/ember__component": "^4.0.22",
|
"@types/ember__component": "^4.0.22",
|
||||||
|
@ -61,6 +56,11 @@
|
||||||
"@types/ember__template": "^4.0.7",
|
"@types/ember__template": "^4.0.7",
|
||||||
"@types/ember__test": "^4.0.6",
|
"@types/ember__test": "^4.0.6",
|
||||||
"@types/ember__utils": "^4.0.7",
|
"@types/ember__utils": "^4.0.7",
|
||||||
|
"@types/ember-data": "^4.4.16",
|
||||||
|
"@types/ember-data__adapter": "^4.0.6",
|
||||||
|
"@types/ember-data__model": "^4.0.5",
|
||||||
|
"@types/ember-data__serializer": "^4.0.6",
|
||||||
|
"@types/ember-data__store": "^4.0.7",
|
||||||
"@types/qunit": "^2.19.10",
|
"@types/qunit": "^2.19.10",
|
||||||
"@types/rsvp": "^4.0.9",
|
"@types/rsvp": "^4.0.9",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
||||||
|
@ -79,6 +79,7 @@
|
||||||
"ember-cli-terser": "^4.0.2",
|
"ember-cli-terser": "^4.0.2",
|
||||||
"ember-data": "~5.3.8",
|
"ember-data": "~5.3.8",
|
||||||
"ember-fetch": "^8.1.2",
|
"ember-fetch": "^8.1.2",
|
||||||
|
"ember-infinity": "^3.0.0",
|
||||||
"ember-load-initializers": "^2.1.2",
|
"ember-load-initializers": "^2.1.2",
|
||||||
"ember-modifier": "^4.2.0",
|
"ember-modifier": "^4.2.0",
|
||||||
"ember-page-title": "^8.2.3",
|
"ember-page-title": "^8.2.3",
|
||||||
|
|
21
frontend-reactive/tests/integration/components/note-test.ts
Normal file
21
frontend-reactive/tests/integration/components/note-test.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { module, test } from "qunit";
|
||||||
|
import { setupRenderingTest } from "frontend-reactive/tests/helpers";
|
||||||
|
import { render } from "@ember/test-helpers";
|
||||||
|
import { hbs } from "ember-cli-htmlbars";
|
||||||
|
|
||||||
|
module("Integration | Component | note", function(hooks) {
|
||||||
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
|
test("it renders", async function(assert) {
|
||||||
|
// Set any properties with this.set('myProperty', 'value');
|
||||||
|
// Handle any actions with this.set('myAction', function(val) { ... });
|
||||||
|
|
||||||
|
await render(hbs`
|
||||||
|
<Note @displayname="bob" @username="alice" @serverdomain="example.com" @content="some content"/>
|
||||||
|
`);
|
||||||
|
|
||||||
|
assert.dom("p.note-user-displayname").hasText("bob");
|
||||||
|
assert.dom("p.note-user-handle").hasText("@alice@example.com");
|
||||||
|
assert.dom("p.note-content-text").hasText("some content");
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { module, test } from 'qunit';
|
||||||
|
import { setupRenderingTest } from 'frontend-reactive/tests/helpers';
|
||||||
|
import { render } from '@ember/test-helpers';
|
||||||
|
import { hbs } from 'ember-cli-htmlbars';
|
||||||
|
|
||||||
|
module('Integration | Component | note/content', function (hooks) {
|
||||||
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
|
test('note-content', async function (assert) {
|
||||||
|
// Set any properties with this.set('myProperty', 'value');
|
||||||
|
// Handle any actions with this.set('myAction', function(val) { ... });
|
||||||
|
|
||||||
|
const shortContent = 'Lorem ipsum odor amet, consectetuer adipiscing elit.';
|
||||||
|
this.set('shortContent', shortContent);
|
||||||
|
|
||||||
|
await render(hbs`<Note::Content @content="{{this.shortContent}}"/>`);
|
||||||
|
|
||||||
|
assert.dom('.note-content-text').hasText(shortContent);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { module, test } from "qunit";
|
||||||
|
import { setupRenderingTest } from "frontend-reactive/tests/helpers";
|
||||||
|
import { render } from "@ember/test-helpers";
|
||||||
|
import { hbs } from "ember-cli-htmlbars";
|
||||||
|
|
||||||
|
module("Integration | Component | note/user-header", function(hooks) {
|
||||||
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
|
test("it renders", async function(assert) {
|
||||||
|
// Set any properties with this.set('myProperty', 'value');
|
||||||
|
// Handle any actions with this.set('myAction', function(val) { ... });
|
||||||
|
|
||||||
|
await render(
|
||||||
|
hbs`<Note::UserHeader @displayname="bob" @handle="@alice@example.com"/>`,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.dom("p.note-user-displayname").hasText("bob");
|
||||||
|
assert.dom("p.note-user-handle").hasText("@alice@example.com");
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,25 +0,0 @@
|
||||||
import { module, test } from "qunit";
|
|
||||||
import { setupRenderingTest } from "frontend-reactive/tests/helpers";
|
|
||||||
import { render } from "@ember/test-helpers";
|
|
||||||
import { hbs } from "ember-cli-htmlbars";
|
|
||||||
|
|
||||||
module("Integration | Component | timeline/note", function (hooks) {
|
|
||||||
setupRenderingTest(hooks);
|
|
||||||
|
|
||||||
test("it renders", async function (assert) {
|
|
||||||
// Set any properties with this.set('myProperty', 'value');
|
|
||||||
// Handle any actions with this.set('myAction', function(val) { ... });
|
|
||||||
|
|
||||||
await render(hbs`<Timeline::Note />`);
|
|
||||||
|
|
||||||
assert.dom().hasText("");
|
|
||||||
|
|
||||||
// Template block usage:
|
|
||||||
await render(hbs`
|
|
||||||
<Timeline::Note @username="bob" @content="some content"/>
|
|
||||||
`);
|
|
||||||
|
|
||||||
assert.dom("h3").hasText("bob");
|
|
||||||
assert.dom("p").hasText("some content");
|
|
||||||
});
|
|
||||||
});
|
|
Loading…
Reference in a new issue