diff --git a/hack/fixtures/BUILD.bazel b/hack/fixtures/BUILD.bazel new file mode 100644 index 0000000..b7d5812 --- /dev/null +++ b/hack/fixtures/BUILD.bazel @@ -0,0 +1,10 @@ +load("//:hack/react.bzl", "react_library") + +package(default_visibility = ["//visibility:public"]) + +react_library( + name = "fixtures", + deps = [ + "@roleypoly/rpc", + ], +) diff --git a/hack/fixtures/demoData.ts b/hack/fixtures/demoData.ts new file mode 100644 index 0000000..bc68aa5 --- /dev/null +++ b/hack/fixtures/demoData.ts @@ -0,0 +1,58 @@ +import { Role } from '@roleypoly/rpc/shared'; + +export const demoData: Role.AsObject[] = [ + { + id: '557812805546541066', + name: 'a cute role ♡', + color: 0xd19494, + permissions: 0, + safety: 0, + managed: false, + position: 0, + }, + { + id: '557812901717737472', + name: 'a vanity role ♡', + color: 0xd1d194, + permissions: 0, + safety: 0, + managed: false, + position: 0, + }, + { + id: '557812915386843170', + name: 'a brave role ♡', + color: 0x94d194, + permissions: 0, + safety: 0, + managed: false, + position: 0, + }, + { + id: '557824893241131029', + name: 'a proud role ♡', + color: 0x94d1d1, + permissions: 0, + safety: 0, + managed: false, + position: 0, + }, + { + id: '557824994269200384', + name: 'a wonderful role ♡', + color: 0x9494d1, + permissions: 0, + safety: 0, + managed: false, + position: 0, + }, + { + id: '557825026406088717', + name: 'a 日本語 role ♡', + color: 0xd194d1, + permissions: 0, + safety: 0, + managed: false, + position: 0, + }, +]; diff --git a/hack/fixtures/storyData.ts b/hack/fixtures/storyData.ts new file mode 100644 index 0000000..d303557 --- /dev/null +++ b/hack/fixtures/storyData.ts @@ -0,0 +1,237 @@ +import { Member } from '@roleypoly/rpc/discord'; +import { Category, GuildData, GuildEnumeration } from '@roleypoly/rpc/platform'; +import { + DiscordUser, + Guild, + GuildRoles, + Role, + RoleypolyUser, +} from '@roleypoly/rpc/shared'; + +export const roleCategory: Role.AsObject[] = [ + { + id: 'aaa', + permissions: 0, + name: 'She/Her', + color: 0xffc0cb, + position: 1, + managed: false, + safety: Role.RoleSafety.SAFE, + }, + { + id: 'bbb', + permissions: 0, + name: 'He/Him', + color: 0xc0ebff, + position: 2, + managed: false, + safety: Role.RoleSafety.SAFE, + }, + { + id: 'ccc', + permissions: 0, + name: 'They/Them', + color: 0xc0ffd5, + position: 3, + managed: false, + safety: Role.RoleSafety.SAFE, + }, + { + id: 'ddd', + permissions: 0, + name: 'Reee', + color: 0xff0000, + position: 4, + managed: false, + safety: Role.RoleSafety.SAFE, + }, + { + id: 'eee', + permissions: 0, + name: 'black but actually bravely default', + color: 0x000000, + position: 5, + managed: false, + safety: Role.RoleSafety.SAFE, + }, + { + id: 'fff', + permissions: 0, + name: 'b̻͌̆̽ͣ̃ͭ̊l͚̥͙̔ͨ̊aͥć͕k͎̟͍͕ͥ̋ͯ̓̈̉̋i͛̄̔͂̚̚҉̳͈͔̖̼̮ṣ̤̗̝͊̌͆h͈̭̰͔̥̯ͅ', + color: 0x1, + position: 6, + managed: false, + safety: Role.RoleSafety.SAFE, + }, + { + id: 'unsafe1', + permissions: 0, + name: 'too high', + color: 0xff0088, + position: 7, + managed: false, + safety: Role.RoleSafety.HIGHERTHANBOT, + }, + { + id: 'unsafe2', + permissions: 0x00000008 | 0x10000000, + name: 'too strong', + color: 0x00ff88, + position: 8, + managed: false, + safety: Role.RoleSafety.DANGEROUSPERMISSIONS, + }, +]; + +export const mockCategory: Category.AsObject = { + id: 'aaa', + name: 'Mock', + rolesList: roleCategory.map((x) => x.id), + hidden: false, + type: Category.CategoryType.MULTI, + position: 0, +}; + +export const roleCategory2: Role.AsObject[] = [ + { + id: 'ddd2', + permissions: 0, + name: 'red', + color: 0xff0000, + position: 9, + managed: false, + safety: Role.RoleSafety.SAFE, + }, + { + id: 'eee2', + permissions: 0, + name: 'green', + color: 0x00ff00, + position: 10, + managed: false, + safety: Role.RoleSafety.SAFE, + }, +]; + +export const mockCategorySingle: Category.AsObject = { + id: 'bbb', + name: 'Mock Single 岡野', + rolesList: roleCategory2.map((x) => x.id), + hidden: false, + type: Category.CategoryType.SINGLE, + position: 0, +}; + +export const guildRoles: GuildRoles.AsObject = { + id: 'aaa', + rolesList: [...roleCategory, ...roleCategory2], +}; + +export const roleWikiData = { + aaa: 'Typically used by feminine-identifying people', + bbb: 'Typically used by masculine-identifying people', + ccc: 'Typically used to refer to all people as a singular neutral.', +}; + +export const guild: Guild.AsObject = { + name: 'emoji megaporium', + id: 'aaa', + icon: + 'https://cdn.discordapp.com/icons/421896162539470888/3372fd895ed913b55616c5e49cd50e60.png?size=256', + ownerid: 'bbb', + membercount: 23453, + splash: '', +}; + +export const guildMap: { [x: string]: Guild.AsObject } = { + 'emoji megaporium': guild, + Roleypoly: { + name: 'Roleypoly', + id: 'aaa', + icon: + 'https://cdn.discordapp.com/icons/203493697696956418/ff08d36f5aee1ff48f8377b65d031ab0.png?size=256', + ownerid: 'bbb', + membercount: 23453, + splash: '', + }, + 'chamber of secrets': { + name: 'chamber of secrets', + id: 'aaa', + icon: '', + ownerid: 'bbb', + membercount: 23453, + splash: '', + }, + Eclipse: { + name: 'Eclipse', + id: 'aaa', + icon: + 'https://cdn.discordapp.com/icons/408821059161423873/49dfdd8b2456e2977e80a8b577b19c0d.png?size=256', + ownerid: 'bbb', + membercount: 23453, + splash: '', + }, +}; + +export const guildData: GuildData.AsObject = { + id: 'aaa', + message: 'henlo worl!!', + categoriesList: [mockCategory, mockCategorySingle], + entitlementsList: [], +}; + +export const user: DiscordUser.AsObject = { + id: '123', + username: 'okano cat', + discriminator: '3266', + avatar: + 'https://cdn.discordapp.com/avatars/62601275618889728/b1292bb974557337702cb941fc038085.png', + bot: false, +}; + +export const member: Member.AsObject = { + guildid: 'aaa', + rolesList: ['aaa', 'eee', 'unsafe2', 'ddd2'], + nick: 'okano cat', + user: user, +}; + +export const rpUser: RoleypolyUser.AsObject = { + discorduser: user, +}; + +export const guildEnum: GuildEnumeration.AsObject = { + guildsList: [ + { + id: 'aaa', + guild: guildMap['emoji megaporium'], + member, + data: guildData, + roles: guildRoles, + }, + { + id: 'bbb', + guild: guildMap['Roleypoly'], + member: { + ...member, + rolesList: ['unsafe2'], + }, + data: guildData, + roles: guildRoles, + }, + { + id: 'ccc', + guild: guildMap['chamber of secrets'], + member, + data: guildData, + roles: guildRoles, + }, + { + id: 'ddd', + guild: guildMap['Eclipse'], + member, + data: guildData, + roles: guildRoles, + }, + ], +}; diff --git a/package.json b/package.json index 019b51b..5fbea97 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ }, "homepage": "https://github.com/roleypoly/roleypoly#readme", "dependencies": { + "@roleypoly/rpc": "^1.9.3", "chroma-js": "2.1.0", "next": "^9.5.4", "react": "16.13.1", @@ -48,4 +49,4 @@ "tslint-plugin-prettier": "^2.3.0", "typescript": "^4.0.3" } -} \ No newline at end of file +} diff --git a/src/design-system/atoms/role/BUILD.bazel b/src/design-system/atoms/role/BUILD.bazel index 67e7b6e..1cf08f0 100644 --- a/src/design-system/atoms/role/BUILD.bazel +++ b/src/design-system/atoms/role/BUILD.bazel @@ -11,6 +11,7 @@ react_library( "styled-components", "//src/design-system/atoms/colors", "//src/design-system/atoms/timings", + "@roleypoly/rpc", "@types/chroma-js", "@types/react", "@types/styled-components", diff --git a/src/design-system/atoms/role/Role.stories.tsx b/src/design-system/atoms/role/Role.stories.tsx new file mode 100644 index 0000000..637a57f --- /dev/null +++ b/src/design-system/atoms/role/Role.stories.tsx @@ -0,0 +1,79 @@ +import * as React from "react"; +import { Role as RoleComponent } from "./Role"; +import { roleCategory } from "roleypoly/hack/fixtures/storyData"; +import { withColors } from "roleypoly/src/design-system/atoms/colors/withColors"; +import styled from "styled-components"; + +export default { + title: "Atoms/Role", + component: RoleComponent, + decorators: [withColors], +}; + +const Demo = styled.div` + display: flex; + flex-wrap: wrap; +`; + +const RoleWithState = (props: any) => { + const [selected, updateSelected] = React.useState(false); + return ( +
+ updateSelected(next)} + /> +
+ ); +}; + +export const Role = () => ( + + {roleCategory.map((c, idx) => ( + + ))} + +); + +export const Selected = () => ( + + {roleCategory.map((c, idx) => ( + + ))} + +); + +export const Unselected = () => ( + + {roleCategory.map((c, idx) => ( + + ))} + +); + +export const DisabledByPosition = () => ( + + {roleCategory.map((c, idx) => ( + + ))} + +); + +export const DisabledByDanger = () => ( + + {roleCategory.map((c, idx) => ( + + ))} + +); diff --git a/src/design-system/atoms/role/Role.story.tsx b/src/design-system/atoms/role/Role.story.tsx deleted file mode 100644 index bca2d64..0000000 --- a/src/design-system/atoms/role/Role.story.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import * as React from 'react'; -import { atomStories } from 'atoms/atoms.story'; -import { Role } from './Role'; -import { roleCategory } from 'hack/fixtures/storyData'; -import { withColors } from 'atoms/colors/withColors'; -import styled from 'styled-components'; - -const story = atomStories('Role', module); - -story.addDecorator(withColors); - -const Demo = styled.div` - display: flex; - flex-wrap: wrap; -`; - -const RoleWithState = (props: any) => { - const [selected, updateSelected] = React.useState(false); - return ( -
- updateSelected(next)} - /> -
- ); -}; - -story.add('Role', () => { - return ( - - {roleCategory.map((c, idx) => ( - - ))} - - ); -}); - -story.add('Selected', () => ( - - {roleCategory.map((c, idx) => ( - - ))} - -)); - -story.add('Unselected', () => ( - - {roleCategory.map((c, idx) => ( - - ))} - -)); - -story.add('Disabled (Position)', () => ( - - {roleCategory.map((c, idx) => ( - - ))} - -)); - -story.add('Disabled (Dangerous)', () => ( - - {roleCategory.map((c, idx) => ( - - ))} - -)); diff --git a/src/design-system/atoms/role/Role.tsx b/src/design-system/atoms/role/Role.tsx index 0ab80ef..237d093 100644 --- a/src/design-system/atoms/role/Role.tsx +++ b/src/design-system/atoms/role/Role.tsx @@ -1,11 +1,12 @@ import * as React from "react"; +import { Role as RPCRole } from "@roleypoly/rpc/shared"; import * as styled from "./Role.styled"; import { FaCheck, FaTimes } from "react-icons/fa"; import { numberToChroma } from "roleypoly/src/design-system/atoms/colors"; import chroma from "chroma-js"; type Props = { - role: any; // TODO: rpc types + role: RPCRole.AsObject; selected: boolean; disabled?: boolean; onClick?: (newState: boolean) => void; @@ -59,11 +60,11 @@ export const Role = (props: Props) => { ); }; -const disabledReason = (role: any) => { +const disabledReason = (role: RPCRole.AsObject) => { switch (role.safety) { - case 1: + case RPCRole.RoleSafety.HIGHERTHANBOT: return `This role is above Roleypoly's own role.`; - case 2: + case RPCRole.RoleSafety.DANGEROUSPERMISSIONS: const { permissions } = role; let permissionHits: string[] = []; diff --git a/yarn.lock b/yarn.lock index fcd1147..3c219ff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1245,6 +1245,13 @@ resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8" integrity sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw== +"@improbable-eng/grpc-web@0.13.0": + version "0.13.0" + resolved "https://registry.yarnpkg.com/@improbable-eng/grpc-web/-/grpc-web-0.13.0.tgz#289e6fc4dafc00b1af8e2b93b970e6892299014d" + integrity sha512-vaxxT+Qwb7GPqDQrBV4vAAfH0HywgOLw6xGIKXd9Q8hcV63CQhmS3p4+pZ9/wVvt4Ph3ZDK9fdC983b9aGMUFg== + dependencies: + browser-headers "^0.4.0" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -1451,6 +1458,14 @@ prop-types "^15.6.1" react-lifecycles-compat "^3.0.4" +"@roleypoly/rpc@^1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@roleypoly/rpc/-/rpc-1.9.3.tgz#b4b7358bb82ce63f70831c2d0054ca30a46d4a38" + integrity sha512-9Bi1kaBRQ9R//ZcpRf+zpswVQ3p/5nhYMazm0wo36/PQ7jFaM+7z8rVSLlrkHxITMGOd6PVvEc8J2gPE/fmpLw== + dependencies: + "@improbable-eng/grpc-web" "0.13.0" + google-protobuf "3.13.0" + "@storybook/addon-actions@6.0.26", "@storybook/addon-actions@^6.0.26": version "6.0.26" resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-6.0.26.tgz#d0de9e4d78a8f8f5bf8730c04d0b6d1741c29273" @@ -3428,6 +3443,11 @@ brorand@^1.0.1: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= +browser-headers@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/browser-headers/-/browser-headers-0.4.1.tgz#4308a7ad3b240f4203dbb45acedb38dc2d65dd02" + integrity sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg== + browserify-aes@^1.0.0, browserify-aes@^1.0.4: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" @@ -5730,6 +5750,11 @@ good-listener@^1.2.2: dependencies: delegate "^3.1.2" +google-protobuf@3.13.0: + version "3.13.0" + resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.13.0.tgz#909c5983d75dd6101ed57c79e0528d000cdc3251" + integrity sha512-ZIf3qfLFayVrPvAjeKKxO5FRF1/NwRxt6Dko+fWEMuHwHbZx8/fcaAao9b0wCM6kr8qeg2te8XTpyuvKuD9aKw== + graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"